From 13e80a76bf7bb6b1beedb56b20d593b348c1f248 Mon Sep 17 00:00:00 2001 From: elwessdev Date: Sun, 3 May 2026 17:01:22 +0100 Subject: [PATCH 01/30] FEAT - assign free plan scan to patient when upgrade --- .../features/dashboard/ScanResults/hooks.ts | 14 ++ .../features/dashboard/ScanResults/index.tsx | 148 ++++++++++++------ .../features/dashboard/UploadMRIScan/hooks.ts | 1 + .../src/ScanResult/scan_result.controller.ts | 9 ++ server/src/ScanResult/scan_result.service.ts | 19 +++ server/src/main.ts | 2 +- 6 files changed, 146 insertions(+), 47 deletions(-) diff --git a/client/src/features/dashboard/ScanResults/hooks.ts b/client/src/features/dashboard/ScanResults/hooks.ts index 2c55844..759e580 100644 --- a/client/src/features/dashboard/ScanResults/hooks.ts +++ b/client/src/features/dashboard/ScanResults/hooks.ts @@ -38,6 +38,20 @@ export const useDeleteScan = () => { }); }; +// Assign Patient to Scan +export const useAssignPatient = () => { + return useMutation({ + mutationFn: async ({ scanId, patientId }: { scanId: string; patientId: string | null }) => { + const response = await axiosInstance.patch(`/scan-result/${scanId}/patient`, { patientId }); + return response.data; + }, + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ['scanResults'] }); + queryClient.invalidateQueries({ queryKey: ['patients'] }); + }, + }); +}; + // Generate Report export const useGenerateReport = () => { return useMutation({ diff --git a/client/src/features/dashboard/ScanResults/index.tsx b/client/src/features/dashboard/ScanResults/index.tsx index b5582b9..76a29d5 100644 --- a/client/src/features/dashboard/ScanResults/index.tsx +++ b/client/src/features/dashboard/ScanResults/index.tsx @@ -11,9 +11,10 @@ import { MdSearchOff, MdAccessTime, } from "react-icons/md"; -import { message, Popconfirm, Select, Table } from "antd"; +import { Dropdown, message, Popconfirm, Select, Table } from "antd"; import type { ColumnsType } from "antd/es/table"; -import { useDeleteScan, useFetchScanResults } from "./hooks"; +import { useDeleteScan, useFetchScanResults, useAssignPatient } from "./hooks"; +import { usePatients } from "../Patients/hooks"; import { useAuthStore } from "../../../store/auth.store"; import type { Scan } from "./types"; import { PAGE_SIZE } from "./types"; @@ -33,6 +34,8 @@ export const ScanResultsPage = () => { const user = useAuthStore((state) => state.user); const { data: scanResults, isLoading: scanResultsLoading } = useFetchScanResults(); + const { data: patients } = usePatients(); + const { mutate: assignPatient, isPending: assignLoading } = useAssignPatient(); const filtered = useMemo(() => { const source: Scan[] = (scanResults as Scan[]) || []; @@ -45,7 +48,7 @@ export const ScanResultsPage = () => { const matchStatus = !statusFilter || s.status === statusFilter; return matchSearch && matchType && matchStatus; }); - }, [scanResults, search, typeFilter, statusFilter, user?.plan]); + }, [scanResults, search, typeFilter, statusFilter]); const totalPages = Math.max(1, Math.ceil(filtered.length / PAGE_SIZE)); const currentPage = Math.min(page, totalPages); @@ -464,51 +467,104 @@ export const ScanResultsPage = () => { key: "actions", onHeaderCell: () => ({ style: headerCellStyle("right") }), onCell: () => ({ style: { ...bodyCellStyle, textAlign: "right" } }), - render: (_, scan) => ( -
- {scan?.report && ( - { - e.stopPropagation(); - navigate({ to: "/reports/$id", params: { id: scan.report.code } }); - }} - > - - View Report - - )} - {( - (user?.plan != "FREE" && user?.org == null) || - (canDelete(user) && user?.plan != "FREE") - ) && ( - e.stopPropagation()}> - handleDelete(scan.id)} - disabled={deleteLoading} + render: (_, scan) => { + const patientItems: import("antd").MenuProps["items"] = (patients as import("../Patients/types").Patient[] | undefined)?.map((p) => ({ + key: p.id, + label: ( +
+
+ +
+
+
{p.full_name}
+
CIN: {p.cin}
+
+
+ ), + })) ?? []; + + return ( +
+ {scan?.report && ( + { + e.stopPropagation(); + navigate({ to: "/reports/$id", params: { id: scan.report.code } }); + }} > - {}} + + View Report + + )} + {( + user?.plan !== "FREE" && + !scan?.patient && + user?.org == null + ) && ( + e.stopPropagation()}> + assignPatient({ scanId: scan.id, patientId: key }), + }} + trigger={["click"]} + placement="bottomRight" + disabled={assignLoading} > - - Delete - - - - )} -
- ), + e.stopPropagation()} + > + + Assign Patient + + +
+ )} + {( + (user?.plan != "FREE" && user?.org == null) || + (canDelete(user) && user?.plan != "FREE") + ) && ( + e.stopPropagation()}> + handleDelete(scan.id)} + disabled={deleteLoading} + > + {}} + > + + Delete + + + + )} +
+ ); + }, }, ]; diff --git a/client/src/features/dashboard/UploadMRIScan/hooks.ts b/client/src/features/dashboard/UploadMRIScan/hooks.ts index 14f7882..bf705cd 100644 --- a/client/src/features/dashboard/UploadMRIScan/hooks.ts +++ b/client/src/features/dashboard/UploadMRIScan/hooks.ts @@ -12,6 +12,7 @@ export const useAnalyzeMRI = () => { onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['scanResults'] }); queryClient.invalidateQueries({ queryKey: ['reports'] }); + queryClient.invalidateQueries({ queryKey: ['patients'] }); }, }); }; \ No newline at end of file diff --git a/server/src/ScanResult/scan_result.controller.ts b/server/src/ScanResult/scan_result.controller.ts index b0eb717..ae5cdf0 100644 --- a/server/src/ScanResult/scan_result.controller.ts +++ b/server/src/ScanResult/scan_result.controller.ts @@ -5,6 +5,7 @@ import { Get, Param, Delete, + Patch, } from '@nestjs/common'; import { ScanResultService } from './scan_result.service'; import { JwtAccessGuard } from 'src/auth/guards/jwt-access.guard'; @@ -32,6 +33,14 @@ export class ScanResultController { return this.scanResultService.getScanResultDetail(resultId); } + // Assign Patient to Scan + @UseGuards(JwtAccessGuard, PlanGuard) + @RequirePlan('DOCTOR', 'ORGANIZATION') + @Patch(':resultId/patient') + async assignPatient(@Param('resultId') resultId: string, @Body() body: { patientId: string | null }) { + return this.scanResultService.assignPatient(resultId, body.patientId); + } + // Delete Scan @UseGuards(JwtAccessGuard, PlanGuard) @RequirePlan('DOCTOR', 'ORGANIZATION') diff --git a/server/src/ScanResult/scan_result.service.ts b/server/src/ScanResult/scan_result.service.ts index 3a201b9..f0aa67e 100644 --- a/server/src/ScanResult/scan_result.service.ts +++ b/server/src/ScanResult/scan_result.service.ts @@ -89,6 +89,25 @@ export class ScanResultService { }); } + // Assign Patient to Scan + async assignPatient(resultId: string, patientId: string | null) { + const userId = this.organizationService.getUserId(); + const isMember = await this.organizationService.isUnderOrg(); + + const whereClause = isMember + ? { id: resultId, orgId: await this.organizationService.getOrganizationId() } + : { id: resultId, uploadedById: userId }; + + const scan = await this.prisma.scan.findFirst({ where: whereClause }); + if (!scan) throw new Error('Scan not found or access denied'); + + return this.prisma.scan.update({ + where: { id: resultId }, + data: { patientId }, + include: { patient: true }, + }); + } + // Delete Scan async deleteScanResult(resultId: string) { const userId = this.organizationService.getUserId(); diff --git a/server/src/main.ts b/server/src/main.ts index 3af6fe1..85cf7d0 100644 --- a/server/src/main.ts +++ b/server/src/main.ts @@ -52,7 +52,7 @@ async function bootstrap() { app.enableCors({ origin: process.env.CLIENT_URL?.split(','), credentials: true, - methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'], + methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS', 'PATCH'], allowedHeaders: ['Content-Type', 'Authorization', 'Accept'], }); From 6066b32f43154f7808263fbf06aa8bcd20e65ac8 Mon Sep 17 00:00:00 2001 From: elwessdev Date: Tue, 5 May 2026 21:35:50 +0100 Subject: [PATCH 02/30] close notification --- .../dashboard/Notifications/NotificationDetail.tsx | 9 +++++++-- client/src/features/dashboard/Notifications/index.tsx | 11 ++++++++++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/client/src/features/dashboard/Notifications/NotificationDetail.tsx b/client/src/features/dashboard/Notifications/NotificationDetail.tsx index 487fdeb..4f9f550 100644 --- a/client/src/features/dashboard/Notifications/NotificationDetail.tsx +++ b/client/src/features/dashboard/Notifications/NotificationDetail.tsx @@ -7,9 +7,10 @@ import { useNavigate } from "@tanstack/react-router"; type Props = { n: Notification; onBack: () => void; + onClose: () => void; }; -export const NotificationDetail = ({ n, onBack }: Props) => { +export const NotificationDetail = ({ n, onBack, onClose }: Props) => { const s = TYPE_STYLES[n.type]; const { Icon } = s; const navigate = useNavigate(); @@ -87,7 +88,10 @@ export const NotificationDetail = ({ n, onBack }: Props) => {
diff --git a/client/src/features/dashboard/Notifications/index.tsx b/client/src/features/dashboard/Notifications/index.tsx index 61f91e1..e48d2bf 100644 --- a/client/src/features/dashboard/Notifications/index.tsx +++ b/client/src/features/dashboard/Notifications/index.tsx @@ -165,6 +165,11 @@ export const NotificationsDropdown = () => { readNotifications(unreadIds); }; + const handleClose = () => { + setOpen(false); + setSelected(null); + }; + return (
@@ -203,7 +208,11 @@ export const NotificationsDropdown = () => { }} > {selected ? ( - setSelected(null)} /> + setSelected(null)} + onClose={handleClose} + /> ) : ( Date: Thu, 7 May 2026 23:05:17 +0100 Subject: [PATCH 03/30] chore: add a blank line for better code readability in NotificationDetail.tsx --- .../src/features/dashboard/Notifications/NotificationDetail.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/client/src/features/dashboard/Notifications/NotificationDetail.tsx b/client/src/features/dashboard/Notifications/NotificationDetail.tsx index 4f9f550..7752c16 100644 --- a/client/src/features/dashboard/Notifications/NotificationDetail.tsx +++ b/client/src/features/dashboard/Notifications/NotificationDetail.tsx @@ -10,6 +10,7 @@ type Props = { onClose: () => void; }; + export const NotificationDetail = ({ n, onBack, onClose }: Props) => { const s = TYPE_STYLES[n.type]; const { Icon } = s; From dc8e3c6903f715861a39e78ee056e6853d695e3c Mon Sep 17 00:00:00 2001 From: elwessdev Date: Fri, 8 May 2026 12:05:38 +0100 Subject: [PATCH 04/30] feat: implement report generation and job status polling --- .../dashboard/ScanResults/ReportCard.tsx | 87 ++++-- .../features/dashboard/ScanResults/hooks.ts | 28 +- docker-compose.yml | 13 + server/package-lock.json | 272 +++++++++++++++++- server/package.json | 2 + server/src/Public-API/ApiKeyGuard.ts | 2 +- server/src/Report/report.controller.ts | 9 +- server/src/Report/report.module.ts | 5 +- server/src/Report/report.processor.ts | 152 ++++++++++ server/src/Report/report.service.ts | 145 +++------- server/src/app.module.ts | 12 + server/tsconfig.json | 3 + 12 files changed, 601 insertions(+), 129 deletions(-) create mode 100644 server/src/Report/report.processor.ts diff --git a/client/src/features/dashboard/ScanResults/ReportCard.tsx b/client/src/features/dashboard/ScanResults/ReportCard.tsx index c9fdb55..f51d3af 100644 --- a/client/src/features/dashboard/ScanResults/ReportCard.tsx +++ b/client/src/features/dashboard/ScanResults/ReportCard.tsx @@ -5,7 +5,7 @@ import { OutlineBtn } from "./components"; import { Link, useNavigate } from "@tanstack/react-router"; import { Tooltip, message } from "antd"; import { useAuthStore } from "../../../store/auth.store"; -import { useGenerateReport } from "./hooks"; +import { useGenerateReport, useJobStatus } from "./hooks"; import { useQueryClient } from "@tanstack/react-query"; import type { ApiReportDetail } from "../Reports/types"; import { generateReportPDF } from "../Reports/generateReportPDF"; @@ -85,6 +85,27 @@ const GenerateStep = ({ ); }; +// localStorage helpers for persisting pending jobs across page navigations +const PENDING_JOBS_KEY = 'pending_report_jobs'; +const getPendingJob = (scanId: string): string | null => { + try { return JSON.parse(localStorage.getItem(PENDING_JOBS_KEY) ?? '{}')[scanId] ?? null; } + catch { return null; } +}; +const setPendingJob = (scanId: string, jobId: string) => { + try { + const jobs = JSON.parse(localStorage.getItem(PENDING_JOBS_KEY) ?? '{}'); + jobs[scanId] = jobId; + localStorage.setItem(PENDING_JOBS_KEY, JSON.stringify(jobs)); + } catch {} +}; +const clearPendingJob = (scanId: string) => { + try { + const jobs = JSON.parse(localStorage.getItem(PENDING_JOBS_KEY) ?? '{}'); + delete jobs[scanId]; + localStorage.setItem(PENDING_JOBS_KEY, JSON.stringify(jobs)); + } catch {} +}; + export const ReportCard = ({ scan }: { scan: ScanDetail }) => { const report = scan.report; const incrementTotalReports = useAuthStore((s) => s.incrementTotalReports); @@ -94,10 +115,47 @@ export const ReportCard = ({ scan }: { scan: ScanDetail }) => { const remainingReports = isFree ? Math.max(0, REPORT_FREE_LIMIT - (user?.total_reports ?? 0)) : null; const reportLimitReached = isFree && remainingReports === 0; const canGenerate = (!isDoctorMember || scan.uploadedById === user?.id) && !reportLimitReached; - const [state, setState] = useState(report ? "done" : "none"); + + // Restore pending job from localStorage on mount (user navigated away and came back) + const [jobId, setJobId] = useState(() => + report ? null : getPendingJob(scan.uid) + ); + const [state, setState] = useState( + report ? "done" : getPendingJob(scan.uid) ? "generating" : "none" + ); const [stepsDone, setStepsDone] = useState(0); const [errorMsg, setErrorMsg] = useState(""); + // Poll job status while a jobId is active + const { data: jobStatus } = useJobStatus(jobId); + + // React to job status changes + useEffect(() => { + if (!jobStatus) return; + + if (jobStatus.state === 'completed') { + clearPendingJob(scan.uid); + setJobId(null); + if (isFree) incrementTotalReports(); + setStepsDone(GENERATE_STEPS.length); + queryClient.invalidateQueries({ queryKey: ['scanDetail', scan.uid] }); + queryClient.invalidateQueries({ queryKey: ['reports'] }); + setTimeout(() => { + setState("done"); + queryClient.invalidateQueries({ queryKey: ['scanResults'] }); + navigate({ to: `/reports/${jobStatus.result.code}` }); + }, 600); + } + + if (jobStatus.state === 'failed') { + clearPendingJob(scan.uid); + setJobId(null); + setState("error"); + setErrorMsg(jobStatus.error || "Report generation failed. Please try again."); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [jobStatus?.state]); + // PDF download const queryClient = useQueryClient(); const [pdfLoading, setPdfLoading] = useState(false); @@ -127,8 +185,7 @@ export const ReportCard = ({ scan }: { scan: ScanDetail }) => { // Handle generate const { mutate: generateReport } = useGenerateReport(); const startGenerate = () => { - - if(isFree && user.total_reports >= REPORT_FREE_LIMIT) { + if (isFree && user.total_reports >= REPORT_FREE_LIMIT) { message.error(`Free plan users can only generate up to ${REPORT_FREE_LIMIT} reports. Please upgrade your plan for unlimited access.`); return; } @@ -136,32 +193,30 @@ export const ReportCard = ({ scan }: { scan: ScanDetail }) => { setState("generating"); setStepsDone(0); setErrorMsg(""); + + // Advance first 2 steps via timer; step 3 advances only when the job completes let done = 0; timerRef.current = setInterval(() => { done += 1; setStepsDone(done); - if (done >= GENERATE_STEPS.length) clearInterval(timerRef.current!); + if (done >= GENERATE_STEPS.length - 1) clearInterval(timerRef.current!); }, 1800); generateReport(scan.uid, { - onSuccess: (data: { success: boolean; message?: string; data?: { code?: string } }) => { - clearInterval(timerRef.current!); - if (data.success) { - if(isFree) { - incrementTotalReports(); - } - setStepsDone(GENERATE_STEPS.length); - setTimeout(() => setState("done"), 600); - navigate({ to: `/reports/${data.data?.code ?? ""}` }); + onSuccess: (data) => { + if (data.success && data.jobId) { + setPendingJob(scan.uid, data.jobId); + setJobId(data.jobId); } else { + clearInterval(timerRef.current!); setState("error"); - setErrorMsg(data.message || "Failed to generate report. Please try again."); + setErrorMsg(data.message || "Failed to queue report. Please try again."); } }, onError: () => { clearInterval(timerRef.current!); setState("error"); - setErrorMsg("Failed to generate report. Please try again."); + setErrorMsg("Failed to queue report. Please try again."); }, }); }; diff --git a/client/src/features/dashboard/ScanResults/hooks.ts b/client/src/features/dashboard/ScanResults/hooks.ts index 759e580..8da536f 100644 --- a/client/src/features/dashboard/ScanResults/hooks.ts +++ b/client/src/features/dashboard/ScanResults/hooks.ts @@ -52,16 +52,34 @@ export const useAssignPatient = () => { }); }; -// Generate Report +// Generate Report — enqueues a background job, returns { success, jobId } export const useGenerateReport = () => { return useMutation({ mutationFn: async (scanId: string) => { const response = await axiosInstance.post('/report/generate', { scan_id: scanId }); - return response.data; + return response.data as { success: boolean; jobId?: string; message?: string }; }, - onSuccess: (_data, scanId) => { - queryClient.invalidateQueries({ queryKey: ['scanDetail', scanId] }); - queryClient.invalidateQueries({ queryKey: ['reports'] }); + }); +}; + +type JobStatus = + | { success: boolean; state: 'waiting' | 'active' | 'delayed' | 'prioritized' } + | { success: boolean; state: 'completed'; result: { reportId: string; code: string } } + | { success: boolean; state: 'failed'; error: string }; + +// Poll job status — stops automatically once the job reaches a terminal state +export const useJobStatus = (jobId: string | null) => { + return useQuery({ + queryKey: ['reportJob', jobId], + queryFn: async () => { + const response = await axiosInstance.get(`/report/job/${jobId}`); + return response.data as JobStatus; + }, + enabled: !!jobId, + refetchInterval: (query) => { + const s = query.state.data?.state; + if (s === 'completed' || s === 'failed') return false; + return 3000; }, }); }; \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 8ae624d..2a4c62b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -59,6 +59,19 @@ services: networks: - tumorlens + redis: + image: redis:7-alpine + restart: unless-stopped + volumes: + - redis_data:/data + ports: + - "6380:6379" + networks: + - tumorlens + networks: tumorlens: driver: bridge + +volumes: + redis_data: diff --git a/server/package-lock.json b/server/package-lock.json index e598004..e0455d1 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -10,6 +10,7 @@ "license": "UNLICENSED", "dependencies": { "@aws-sdk/client-s3": "^3.1030.0", + "@nestjs/bullmq": "^11.0.4", "@nestjs/common": "^11.0.1", "@nestjs/config": "^4.0.4", "@nestjs/core": "^11.0.1", @@ -24,6 +25,7 @@ "@types/nodemailer": "^8.0.0", "@types/passport-google-oauth20": "^2.0.17", "bcrypt": "^6.0.0", + "bullmq": "^5.76.6", "class-transformer": "^0.5.1", "class-validator": "^0.15.1", "cloudinary": "^2.9.0", @@ -2281,6 +2283,12 @@ } } }, + "node_modules/@ioredis/commands": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.5.1.tgz", + "integrity": "sha512-JH8ZL/ywcJyR9MmJ5BNqZllXNZQqQbnVZOqpPQqE1vHiFgAw4NHbvE0FOduNU8IX9babitBT46571OnPTT0Zcw==", + "license": "MIT" + }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -2989,6 +2997,84 @@ "node": ">=8" } }, + "node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.3.tgz", + "integrity": "sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.3.tgz", + "integrity": "sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.3.tgz", + "integrity": "sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.3.tgz", + "integrity": "sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-x64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.3.tgz", + "integrity": "sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-win32-x64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.3.tgz", + "integrity": "sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@napi-rs/wasm-runtime": { "version": "0.2.12", "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", @@ -3002,6 +3088,34 @@ "@tybys/wasm-util": "^0.10.0" } }, + "node_modules/@nestjs/bull-shared": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/@nestjs/bull-shared/-/bull-shared-11.0.4.tgz", + "integrity": "sha512-VBJcDHSAzxQnpcDfA0kt9MTGUD1XZzfByV70su0W0eDCQ9aqIEBlzWRW21tv9FG9dIut22ysgDidshdjlnczLw==", + "license": "MIT", + "dependencies": { + "tslib": "2.8.1" + }, + "peerDependencies": { + "@nestjs/common": "^10.0.0 || ^11.0.0", + "@nestjs/core": "^10.0.0 || ^11.0.0" + } + }, + "node_modules/@nestjs/bullmq": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/@nestjs/bullmq/-/bullmq-11.0.4.tgz", + "integrity": "sha512-wBzK9raAVG0/6NTMdvLGM4/FQ1lsB35/pYS8L6a0SDgkTiLpd7mAjQ8R692oMx5s7IjvgntaZOuTUrKYLNfIkA==", + "license": "MIT", + "dependencies": { + "@nestjs/bull-shared": "^11.0.4", + "tslib": "2.8.1" + }, + "peerDependencies": { + "@nestjs/common": "^10.0.0 || ^11.0.0", + "@nestjs/core": "^10.0.0 || ^11.0.0", + "bullmq": "^3.0.0 || ^4.0.0 || ^5.0.0" + } + }, "node_modules/@nestjs/cli": { "version": "11.0.16", "resolved": "https://registry.npmjs.org/@nestjs/cli/-/cli-11.0.16.tgz", @@ -6596,6 +6710,23 @@ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "license": "MIT" }, + "node_modules/bullmq": { + "version": "5.76.6", + "resolved": "https://registry.npmjs.org/bullmq/-/bullmq-5.76.6.tgz", + "integrity": "sha512-vlmL3B3NVMRy6se3c7jPHn1Nhqxrg7+wlv1t3XAQFBYZNJDMLP0OO5x2AX5ca7DAuS1SU/C+VfYi+NHVoFK1QQ==", + "license": "MIT", + "dependencies": { + "cron-parser": "4.9.0", + "ioredis": "5.10.1", + "msgpackr": "2.0.1", + "node-abort-controller": "3.1.1", + "semver": "7.7.4", + "tslib": "2.8.1" + }, + "engines": { + "node": ">=12.22.0" + } + }, "node_modules/busboy": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", @@ -6940,6 +7071,15 @@ "node": ">=9" } }, + "node_modules/cluster-key-slot": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", + "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -7209,6 +7349,18 @@ "url": "https://ko-fi.com/intcreator" } }, + "node_modules/cron-parser": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-4.9.0.tgz", + "integrity": "sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q==", + "license": "MIT", + "dependencies": { + "luxon": "^3.2.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -7350,6 +7502,16 @@ "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==", "license": "MIT" }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=8" + } + }, "node_modules/detect-newline": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", @@ -8887,6 +9049,30 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "license": "ISC" }, + "node_modules/ioredis": { + "version": "5.10.1", + "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.10.1.tgz", + "integrity": "sha512-HuEDBTI70aYdx1v6U97SbNx9F1+svQKBDo30o0b9fw055LMepzpOOd0Ccg9Q6tbqmBSJaMuY0fB7yw9/vjBYCA==", + "license": "MIT", + "dependencies": { + "@ioredis/commands": "1.5.1", + "cluster-key-slot": "^1.1.0", + "debug": "^4.3.4", + "denque": "^2.1.0", + "lodash.defaults": "^4.2.0", + "lodash.isarguments": "^3.1.0", + "redis-errors": "^1.2.0", + "redis-parser": "^3.0.0", + "standard-as-callback": "^2.1.0" + }, + "engines": { + "node": ">=12.22.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ioredis" + } + }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -10136,12 +10322,24 @@ "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", "license": "MIT" }, + "node_modules/lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==", + "license": "MIT" + }, "node_modules/lodash.includes": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", "license": "MIT" }, + "node_modules/lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==", + "license": "MIT" + }, "node_modules/lodash.isboolean": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", @@ -10466,6 +10664,37 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "license": "MIT" }, + "node_modules/msgpackr": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-2.0.1.tgz", + "integrity": "sha512-9J+tqTEsbHqY8YohazYgty7LgerFIWxvMLpUjqETSmjHojtJm2WnX2kK/2a1fLI7CO7ERP1YSEUXMucz4j+yBA==", + "license": "MIT", + "optionalDependencies": { + "msgpackr-extract": "^3.0.2" + } + }, + "node_modules/msgpackr-extract": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/msgpackr-extract/-/msgpackr-extract-3.0.3.tgz", + "integrity": "sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "node-gyp-build-optional-packages": "5.2.2" + }, + "bin": { + "download-msgpackr-prebuilds": "bin/download-prebuilds.js" + }, + "optionalDependencies": { + "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.3", + "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.3" + } + }, "node_modules/multer": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/multer/-/multer-2.1.1.tgz", @@ -10613,7 +10842,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==", - "dev": true, "license": "MIT" }, "node_modules/node-addon-api": { @@ -10652,6 +10880,21 @@ "node-gyp-build-test": "build-test.js" } }, + "node_modules/node-gyp-build-optional-packages": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.2.2.tgz", + "integrity": "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==", + "license": "MIT", + "optional": true, + "dependencies": { + "detect-libc": "^2.0.1" + }, + "bin": { + "node-gyp-build-optional-packages": "bin.js", + "node-gyp-build-optional-packages-optional": "optional.js", + "node-gyp-build-optional-packages-test": "build-test.js" + } + }, "node_modules/node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", @@ -11770,6 +12013,27 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/redis-errors": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", + "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/redis-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", + "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==", + "license": "MIT", + "dependencies": { + "redis-errors": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/reflect-metadata": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", @@ -12244,6 +12508,12 @@ "node": ">=8" } }, + "node_modules/standard-as-callback": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz", + "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==", + "license": "MIT" + }, "node_modules/standardwebhooks": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/standardwebhooks/-/standardwebhooks-1.0.0.tgz", diff --git a/server/package.json b/server/package.json index b7a1b8d..63af320 100644 --- a/server/package.json +++ b/server/package.json @@ -21,6 +21,7 @@ }, "dependencies": { "@aws-sdk/client-s3": "^3.1030.0", + "@nestjs/bullmq": "^11.0.4", "@nestjs/common": "^11.0.1", "@nestjs/config": "^4.0.4", "@nestjs/core": "^11.0.1", @@ -35,6 +36,7 @@ "@types/nodemailer": "^8.0.0", "@types/passport-google-oauth20": "^2.0.17", "bcrypt": "^6.0.0", + "bullmq": "^5.76.6", "class-transformer": "^0.5.1", "class-validator": "^0.15.1", "cloudinary": "^2.9.0", diff --git a/server/src/Public-API/ApiKeyGuard.ts b/server/src/Public-API/ApiKeyGuard.ts index f99125b..d10c4bc 100644 --- a/server/src/Public-API/ApiKeyGuard.ts +++ b/server/src/Public-API/ApiKeyGuard.ts @@ -5,7 +5,7 @@ import { HttpStatus, Injectable, } from "@nestjs/common"; -import { PrismaService } from "prisma/prisma.service"; +import { PrismaService } from "../../prisma/prisma.service"; const RATE_LIMIT_WINDOW_MS = 60_000; const RATE_LIMIT_MAX = 60; diff --git a/server/src/Report/report.controller.ts b/server/src/Report/report.controller.ts index 0967d69..e632151 100644 --- a/server/src/Report/report.controller.ts +++ b/server/src/Report/report.controller.ts @@ -19,13 +19,20 @@ import { export class ReportController { constructor(private reportService: ReportService) {} - // Generate Report + // Generate Report (enqueues job, returns jobId) @UseGuards(JwtAccessGuard) @Post('generate') async generateReport(@Body() body: any) { return this.reportService.generateReport(body); } + // Get Job Status + @UseGuards(JwtAccessGuard) + @Get('job/:jobId') + async getJobStatus(@Param('jobId') jobId: string) { + return this.reportService.getJobStatus(jobId); + } + // Get Reports @UseGuards(JwtAccessGuard) @Get() diff --git a/server/src/Report/report.module.ts b/server/src/Report/report.module.ts index 285129f..7b40b93 100644 --- a/server/src/Report/report.module.ts +++ b/server/src/Report/report.module.ts @@ -1,6 +1,8 @@ import { Module } from '@nestjs/common'; +import { BullModule } from '@nestjs/bullmq'; import { ReportService } from './report.service'; import { ReportController } from './report.controller'; +import { ReportProcessor, REPORT_QUEUE } from './report.processor'; import { PrismaService } from '../../prisma/prisma.service'; import { MailService } from 'src/Notifications/mail.service'; import { OrganizationService } from 'src/Organization/organization.service'; @@ -8,7 +10,8 @@ import { AuditLogService } from 'src/Organization/audit-log.service'; import { PlanGuard } from 'src/auth/guards/plan.guard'; @Module({ + imports: [BullModule.registerQueue({ name: REPORT_QUEUE })], controllers: [ReportController], - providers: [ReportService, PrismaService, OrganizationService, AuditLogService, MailService, PlanGuard], + providers: [ReportService, ReportProcessor, PrismaService, OrganizationService, AuditLogService, MailService, PlanGuard], }) export class ReportModule {} diff --git a/server/src/Report/report.processor.ts b/server/src/Report/report.processor.ts new file mode 100644 index 0000000..0801f44 --- /dev/null +++ b/server/src/Report/report.processor.ts @@ -0,0 +1,152 @@ +import { Processor, WorkerHost } from '@nestjs/bullmq'; +import { Job } from 'bullmq'; +import { PrismaService } from '../../prisma/prisma.service'; +import { EventEmitter2 } from '@nestjs/event-emitter'; + +export const REPORT_QUEUE = 'report'; + +export interface ReportJobData { + scan_id: string; + userId: string; + ip?: string | null; + userAgent?: string | null; +} + +@Processor(REPORT_QUEUE) +export class ReportProcessor extends WorkerHost { + constructor( + private prisma: PrismaService, + private eventEmitter: EventEmitter2, + ) { + super(); + } + + async process(job: Job) { + const { scan_id, userId, ip, userAgent } = job.data; + + const processingStart = Date.now(); + + const scan: any = await this.prisma.scan.findUnique({ + where: { id: scan_id }, + include: { patient: true }, + }); + + if (!scan) throw new Error('Scan not found'); + + const response: any = await fetch( + `${process.env.RAG_REPORT_URL}/report`, + { + method: 'POST', + body: JSON.stringify({ + classification: { + class: scan.class, + confidence: scan.confidence_score, + all_scores: scan.all_scores, + }, + top_k: 10, + }), + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${process.env.RAG_REPORT_API_KEY}`, + }, + }, + ); + + const result = await response.json(); + if (!result.success) throw new Error('RAG API returned failure'); + + const processingEnd = Date.now(); + const processing = (processingEnd - processingStart) / 1000; + + const code = `RPT-${crypto.randomUUID().replace(/-/g, '').slice(0, 8)}`; + await this.prisma.report.upsert({ + where: { scanId: scan_id }, + update: { content: result.report }, + create: { + scanId: scan_id, + content: result, + code, + processing, + }, + }); + + await this.prisma.user.update({ + where: { id: userId }, + data: { total_reports: { increment: 1 } }, + }); + + const report = await this.prisma.report.findUnique({ + where: { scanId: scan_id }, + include: { scan: { include: { patient: true } } }, + }); + + this.eventEmitter.emit('notification.send', { + userId, + type: 'REPORT_COMPLETE', + payload: { reportId: report?.id }, + }); + + await this.writeAuditLog({ + userId, + code: report?.code ?? code, + reportId: report?.id ?? null, + patientName: scan.patient?.full_name ?? null, + ip: ip ?? null, + userAgent: userAgent ?? null, + }); + + return { reportId: report?.id, code: report?.code }; + } + + private async writeAuditLog(params: { + userId: string; + code: string; + reportId: string | null; + patientName: string | null; + ip: string | null; + userAgent: string | null; + }) { + try { + const user = await this.prisma.user.findUnique({ + where: { id: params.userId }, + include: { + ownedOrg: { select: { id: true } }, + orgMember: { + include: { + org: { include: { owner: { select: { plan: true } } } }, + }, + }, + }, + }); + if (!user) return; + + let orgId: string | null = null; + if (user.ownedOrg && user.plan === 'ORGANIZATION') { + orgId = user.ownedOrg.id; + } else if (user.orgMember?.org?.owner?.plan === 'ORGANIZATION') { + orgId = user.orgMember.org.id; + } + if (!orgId) return; + + const target = `${params.code}${params.patientName ? ` · ${params.patientName}` : ''}`; + await this.prisma.auditLog.create({ + data: { + orgId, + actorId: user.id, + actorName: user.username, + actorEmail: user.email, + action: 'report.generated', + category: 'reports', + target, + targetId: params.reportId, + status: 'success', + severity: 'success', + ip: params.ip, + userAgent: params.userAgent, + }, + }); + } catch (err) { + console.error('[audit] failed to write log from processor', err); + } + } +} diff --git a/server/src/Report/report.service.ts b/server/src/Report/report.service.ts index 638df1a..8f4d2f0 100644 --- a/server/src/Report/report.service.ts +++ b/server/src/Report/report.service.ts @@ -1,10 +1,12 @@ import { Injectable, Scope, Inject } from '@nestjs/common'; +import { InjectQueue } from '@nestjs/bullmq'; +import { Queue } from 'bullmq'; import { REQUEST } from '@nestjs/core'; import type { Request } from 'express'; import { PrismaService } from '../../prisma/prisma.service'; import { OrganizationService } from 'src/Organization/organization.service'; import { AuditLogService } from 'src/Organization/audit-log.service'; -import { EventEmitter2 } from '@nestjs/event-emitter'; +import { REPORT_QUEUE, ReportJobData } from './report.processor'; type RequestUser = { userId?: string; @@ -18,9 +20,9 @@ export class ReportService { constructor( private prisma: PrismaService, private organizationService: OrganizationService, - @Inject(REQUEST) private request: AuthenticatedRequest, - private eventEmitter: EventEmitter2, private auditLog: AuditLogService, + @Inject(REQUEST) private request: AuthenticatedRequest, + @InjectQueue(REPORT_QUEUE) private reportQueue: Queue, ) {} // Generate Report @@ -28,121 +30,56 @@ export class ReportService { try { const userId = this.request.user?.userId; if (!userId) { - throw new Error('Unauthorized'); + return { success: false, message: 'Unauthorized' }; } - // Start processing timer - const processingStart = Date.now(); - - // Fetch patient data - const {scan_id} = body; - const scan: any = await this.prisma.scan.findUnique({ - where: { id: scan_id }, - include: { - patient: true, - }, - }); - if(!scan) { - throw new Error('Scan not found'); - } - - // Generate report based on patient data and scan results - const response: any = await fetch( - `${process.env.RAG_REPORT_URL}/report`, - { - method: 'POST', - body: JSON.stringify({ - classification: { - class: scan.class, - confidence: scan.confidence_score, - all_scores: scan.all_scores, - }, - top_k: 10 - }), - headers: { - 'Content-Type': 'application/json', - Authorization: `Bearer ${process.env.RAG_REPORT_API_KEY}`, - }, - }, - ); - const result = await response.json(); - - if (!result.success) { - return { - success: false, - message: "Failed to generate report, please try again later.", - }; + const { scan_id } = body; + const scan = await this.prisma.scan.findUnique({ where: { id: scan_id } }); + if (!scan) { + return { success: false, message: 'Scan not found' }; } - // End processing timer - const processingEnd = Date.now(); - const processing = (processingEnd - processingStart) / 1000; - - // Save report to database - const code = `RPT-${crypto.randomUUID().replace(/-/g, '').slice(0, 8)}`; - await this.prisma.report.upsert({ - where: { scanId: scan_id }, - update: { content: result.report }, - create: { - scanId: scan_id, - content: result, - code, - processing, - }, - }); + const xff = this.request.headers?.['x-forwarded-for']; + const ip = typeof xff === 'string' + ? xff.split(',')[0].trim() + : (this.request.ip ?? null); + const userAgent = (this.request.headers?.['user-agent'] as string) ?? null; - // Increment total_reports for the user - const y = await this.prisma.user.update({ - where: { id: userId }, - data: { - total_reports: { increment: 1 }, - }, + const jobData: ReportJobData = { scan_id, userId, ip, userAgent }; + const job = await this.reportQueue.add('generate', jobData, { + attempts: 3, + backoff: { type: 'exponential', delay: 5000 }, }); - // Return the generated report - const res = await this.prisma.report.findUnique({ - where: { scanId: scan_id }, - include: { - scan: { - include: { - patient: true, - }, - } - }, - }); - - // Send Notification - this.eventEmitter.emit('notification.send', { - userId: userId, - type: 'REPORT_COMPLETE', - payload: { - reportId: res?.id, - } - }); - - // Audit log - await this.auditLog.log({ - action: 'report.generated', - category: 'reports', - target: `${res?.code ?? code}${scan.patient ? ` · ${scan.patient.full_name}` : ''}`, - targetId: res?.id ?? null, - severity: 'success', - }); - - return { - success: true, - data: res, - total_reports: y.total_reports, - }; + return { success: true, jobId: job.id }; } catch (error) { - console.error('Error generating report:', error); + console.error('Error queueing report:', error); return { success: false, - message: "An error occurred while generating the report. Please try again later.", + message: 'An error occurred while queueing the report. Please try again later.', }; } } + // Get Job Status + async getJobStatus(jobId: string) { + const job = await this.reportQueue.getJob(jobId); + if (!job) { + return { success: false, message: 'Job not found' }; + } + + const state = await job.getState(); + + if (state === 'completed') { + return { success: true, state, result: job.returnvalue }; + } + if (state === 'failed') { + return { success: true, state, error: job.failedReason }; + } + + return { success: true, state }; + } + // Get Reports async getReports() { const userId = this.organizationService.getUserId(); diff --git a/server/src/app.module.ts b/server/src/app.module.ts index e6117ae..e885dce 100644 --- a/server/src/app.module.ts +++ b/server/src/app.module.ts @@ -1,6 +1,9 @@ import { Module } from '@nestjs/common'; import { ConfigModule } from '@nestjs/config'; import { ScheduleModule } from '@nestjs/schedule'; +import { BullModule } from '@nestjs/bullmq'; + +// Importing all the modules import { AuthModule } from './auth/auth.module'; import { MriScanModule } from './MriScan/mri_scan.module'; import { ScanResultModule } from './ScanResult/scan_result.module'; @@ -17,9 +20,18 @@ import { PublicApiModule } from './Public-API/public-api.module'; @Module({ imports: [ + // Global Modules ConfigModule.forRoot({ isGlobal: true }), ScheduleModule.forRoot(), EventEmitterModule.forRoot(), + BullModule.forRoot({ + connection: { + host: process.env.REDIS_HOST, + port: parseInt(process.env.REDIS_PORT || '6379'), + }, + }), + + // Modules AuthModule, MriScanModule, ScanResultModule, diff --git a/server/tsconfig.json b/server/tsconfig.json index 8373323..bebb653 100644 --- a/server/tsconfig.json +++ b/server/tsconfig.json @@ -14,6 +14,9 @@ "sourceMap": true, "outDir": "./dist", "baseUrl": "./", + "paths": { + "src/*": ["./src/*"] + }, "incremental": true, "skipLibCheck": true, "strictNullChecks": true, From d912b66644a53596056e557ead75603ee186ad1f Mon Sep 17 00:00:00 2001 From: elwessdev Date: Fri, 8 May 2026 12:11:39 +0100 Subject: [PATCH 05/30] fix: update favicon links and site manifest for proper branding --- client/index.html | 7 ++++++- client/public/favicon_io/site.webmanifest | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/client/index.html b/client/index.html index 54cd8c2..de3c033 100644 --- a/client/index.html +++ b/client/index.html @@ -2,9 +2,14 @@ - TumorLens + + + + + + diff --git a/client/public/favicon_io/site.webmanifest b/client/public/favicon_io/site.webmanifest index 45dc8a2..bd50e81 100644 --- a/client/public/favicon_io/site.webmanifest +++ b/client/public/favicon_io/site.webmanifest @@ -1 +1 @@ -{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"} \ No newline at end of file +{"name":"TumorLens","short_name":"TumorLens","icons":[{"src":"/favicon_io/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"} From 61d3465a3f685bb785402881f2efcd72374b8e0e Mon Sep 17 00:00:00 2001 From: elwessdev Date: Fri, 8 May 2026 13:56:27 +0100 Subject: [PATCH 06/30] chore: improve code readability by adjusting comments and formatting in ReportCard and hooks --- client/src/features/dashboard/ScanResults/ReportCard.tsx | 3 ++- client/src/features/dashboard/ScanResults/hooks.ts | 2 +- server/src/Report/report.service.ts | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/client/src/features/dashboard/ScanResults/ReportCard.tsx b/client/src/features/dashboard/ScanResults/ReportCard.tsx index f51d3af..9a05f91 100644 --- a/client/src/features/dashboard/ScanResults/ReportCard.tsx +++ b/client/src/features/dashboard/ScanResults/ReportCard.tsx @@ -194,7 +194,8 @@ export const ReportCard = ({ scan }: { scan: ScanDetail }) => { setStepsDone(0); setErrorMsg(""); - // Advance first 2 steps via timer; step 3 advances only when the job completes + // Advance first 2 steps via timer; + // step 3 advances only when the job completes let done = 0; timerRef.current = setInterval(() => { done += 1; diff --git a/client/src/features/dashboard/ScanResults/hooks.ts b/client/src/features/dashboard/ScanResults/hooks.ts index 8da536f..1fa60f7 100644 --- a/client/src/features/dashboard/ScanResults/hooks.ts +++ b/client/src/features/dashboard/ScanResults/hooks.ts @@ -62,12 +62,12 @@ export const useGenerateReport = () => { }); }; +// Poll job status — stops automatically once the job reaches a terminal state type JobStatus = | { success: boolean; state: 'waiting' | 'active' | 'delayed' | 'prioritized' } | { success: boolean; state: 'completed'; result: { reportId: string; code: string } } | { success: boolean; state: 'failed'; error: string }; -// Poll job status — stops automatically once the job reaches a terminal state export const useJobStatus = (jobId: string | null) => { return useQuery({ queryKey: ['reportJob', jobId], diff --git a/server/src/Report/report.service.ts b/server/src/Report/report.service.ts index 8f4d2f0..876644e 100644 --- a/server/src/Report/report.service.ts +++ b/server/src/Report/report.service.ts @@ -50,7 +50,7 @@ export class ReportService { attempts: 3, backoff: { type: 'exponential', delay: 5000 }, }); - + return { success: true, jobId: job.id }; } catch (error) { console.error('Error queueing report:', error); From b9b498dcbe2cec304b2d13d4d32071f2e4dca5be Mon Sep 17 00:00:00 2001 From: elwessdev Date: Fri, 8 May 2026 14:22:49 +0100 Subject: [PATCH 07/30] Add favicon images and web manifest for TumorLens --- client/index.html | 8 +++--- .../android-chrome-512x512.png | Bin .../{favicon_io => }/apple-touch-icon.png | Bin .../public/{favicon_io => }/favicon-16x16.png | Bin .../public/{favicon_io => }/favicon-32x32.png | Bin client/public/favicon.svg | 1 - client/public/favicon_io.zip | Bin 293733 -> 0 bytes client/public/icons.svg | 24 ------------------ .../public/{favicon_io => }/site.webmanifest | 0 .../features/dashboard/ScanResults/hooks.ts | 2 +- server/src/Report/report.service.ts | 2 +- 11 files changed, 6 insertions(+), 31 deletions(-) rename client/public/{favicon_io => }/android-chrome-512x512.png (100%) rename client/public/{favicon_io => }/apple-touch-icon.png (100%) rename client/public/{favicon_io => }/favicon-16x16.png (100%) rename client/public/{favicon_io => }/favicon-32x32.png (100%) delete mode 100644 client/public/favicon.svg delete mode 100644 client/public/favicon_io.zip delete mode 100644 client/public/icons.svg rename client/public/{favicon_io => }/site.webmanifest (100%) diff --git a/client/index.html b/client/index.html index de3c033..c151f60 100644 --- a/client/index.html +++ b/client/index.html @@ -6,10 +6,10 @@ TumorLens - - - - + + + + diff --git a/client/public/favicon_io/android-chrome-512x512.png b/client/public/android-chrome-512x512.png similarity index 100% rename from client/public/favicon_io/android-chrome-512x512.png rename to client/public/android-chrome-512x512.png diff --git a/client/public/favicon_io/apple-touch-icon.png b/client/public/apple-touch-icon.png similarity index 100% rename from client/public/favicon_io/apple-touch-icon.png rename to client/public/apple-touch-icon.png diff --git a/client/public/favicon_io/favicon-16x16.png b/client/public/favicon-16x16.png similarity index 100% rename from client/public/favicon_io/favicon-16x16.png rename to client/public/favicon-16x16.png diff --git a/client/public/favicon_io/favicon-32x32.png b/client/public/favicon-32x32.png similarity index 100% rename from client/public/favicon_io/favicon-32x32.png rename to client/public/favicon-32x32.png diff --git a/client/public/favicon.svg b/client/public/favicon.svg deleted file mode 100644 index 6893eb1..0000000 --- a/client/public/favicon.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/client/public/favicon_io.zip b/client/public/favicon_io.zip deleted file mode 100644 index ef9ddbd71ac9c73f6c091acbf81d9a69b5a3a7ae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 293733 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 z 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
{ {/* ════════════ HERO ════════════ */}
{/* Copy */} -
+
@@ -217,26 +245,29 @@ const LandingPage = () => {

- + + +
{/* Visual */} -
+
{
-
+
@@ -330,12 +361,31 @@ const LandingPage = () => { {/* ════════════ FEATURES ════════════ */}
-
- {FEATURES.map((f) => ( +
+
+ Why TumorLens +
+

+ Everything You Need for Confident Diagnostics +

+

+ Built for clinical precision — from instant AI detection to + tamper-proof audit trails, every feature is designed with + radiologists in mind. +

+
+
+ {FEATURES.map((f, idx) => (
{ > {f.title} -

+

{f.desc}

- {/*
+
{f.cta} -
*/} +
))}
@@ -393,7 +443,7 @@ const LandingPage = () => { fast, reliable, and effortless.

-
+
{/* Desktop connectors */}
{[0, 1, 2].map((i) => ( @@ -404,13 +454,14 @@ const LandingPage = () => { /> ))}
- {STEPS.map((s) => ( + {STEPS.map((s, idx) => ( @@ -727,7 +778,7 @@ const LandingPage = () => { }} />
-
+

Date: Mon, 11 May 2026 19:55:16 +0100 Subject: [PATCH 10/30] feat: add CLAUDE.md for project overview and development guidance --- CLAUDE.md | 125 +++++++++++++++++++++++++++++++++++++ server/CLAUDE.md | 156 ----------------------------------------------- 2 files changed, 125 insertions(+), 156 deletions(-) create mode 100644 CLAUDE.md delete mode 100644 server/CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..46311e0 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,125 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +TumorLens is a full-stack medical SaaS for brain tumor detection and reporting. It is a **monorepo** with four independent services: + +| Service | Stack | Port | +|---------|-------|------| +| `client/` | React 19 + Vite + TanStack Router/Query + Ant Design | 5173 | +| `server/` | NestJS 11 + Prisma 7 + PostgreSQL | 3000 | +| `scan_model/` | Python (Gradio) — brain tumor ML model | 7860 | +| `scan_report/` | Python (FastAPI) — RAG report generation | 8000 | + +There is no root `package.json`. Each service is managed independently. + +## Development Commands + +### Client (`cd client`) +```bash +npm run dev # Vite dev server with HMR +npm run build # tsc -b && vite build +npm run lint # ESLint +npm run preview # Preview production build +``` + +### Server (`cd server`) +```bash +npm run start:dev # NestJS watch mode +npm run build # NestJS compile to dist/ +npm run start # Run compiled dist/main.js +npm run test # Jest unit tests (*.spec.ts) +npm run test:e2e # Jest e2e tests +npm run lint # ESLint --fix +npm run format # Prettier +``` + +### Prisma (`cd server`) +```bash +npx prisma migrate dev # Apply migrations in development +npx prisma generate # Regenerate Prisma client after schema changes +npx prisma studio # Visual DB browser +``` + +### Running a single test +```bash +# From server/ +npx jest src/auth/auth.service.spec.ts +npx jest --testPathPattern=auth +``` + +### Full stack via Docker +```bash +docker-compose up # All services (backend, frontend, ML, RAG, postgres, redis) +docker-compose up backend # Single service +``` + +## Architecture + +### Client + +- **Routing**: TanStack Router (`client/src/router.ts`). All protected routes live under the dashboard layout. +- **Data fetching**: TanStack Query wraps all API calls. No direct `axios` calls in components — queries/mutations are co-located in `hooks.ts` files next to each feature. +- **Auth state**: Zustand store (`client/src/store/auth.store.ts`). Tokens are managed via HTTP-only cookies; the store holds user profile data. +- **HTTP client**: Single Axios instance at `client/src/lib/axios.ts` with interceptors for auth headers and 401 handling. +- **Features** live in `client/src/features/` — each folder is a route segment with its own pages, components, and hooks. + +### Server + +- **NestJS modules** are organized by domain in `server/src/`. Each module owns its controller, service, DTOs, and guards. +- **Database access** is exclusively via the Prisma client. No raw SQL outside of Prisma `$queryRaw`. +- **Authentication flow**: JWT access + refresh tokens delivered as HTTP-only cookies. Google OAuth via Passport strategy. 2FA via TOTP (otplib). Password reset via Resend email. +- **Async jobs**: Report generation is queued via BullMQ (Redis). The processor lives in `server/src/Report/`. +- **Real-time**: Server-Sent Events (SSE) for in-app notifications — see `server/src/Notifications/notifications.stream.ts`. +- **Storage**: DigitalOcean Spaces (S3-compatible) via AWS SDK — see `server/src/Storage/`. +- **Plan guards**: `@RequirePlan(Plan.DOCTOR)` decorator/guard enforces subscription tier on routes. +- **Public API**: API key authentication for external integrations in `server/src/Public-API/`. + +### Key data models (Prisma schema in `server/prisma/schema.prisma`) + +- `User` — roles: `USER | ADMIN`; plans: `FREE | DOCTOR | ORGANIZATION`; supports OTP/2FA +- `Organization` → `OrgMember` (multi-tenant hospital/clinic support with audit logs) +- `Patient` → `Scan` → `ScanResult` (core clinical data chain) +- `Subscription` + `Payment` (Stripe billing) +- `Session` (refresh token store) +- `ApiKey` (public API access) + +### ML services + +- `scan_model/` exposes a Gradio API; the NestJS server calls it via HTTP at `ML_MODEL_URL`. +- `scan_report/` exposes a FastAPI endpoint; the server calls it to generate RAG-based PDF reports. + +## Environment Setup + +**Server** — create `server/.env`: +``` +DATABASE_URL=postgresql://... +JWT_ACCESS_SECRET=... +JWT_REFRESH_SECRET=... +GOOGLE_CLIENT_ID=... +GOOGLE_CLIENT_SECRET=... +ML_MODEL_URL=http://localhost:7860 +ML_MODEL_API_KEY=... +DIGITAL_OCEAN_SPACE_KEY=... +DIGITAL_OCEAN_SPACE_SECRET=... +DIGITAL_OCEAN_SPACE_ENDPOINT=... +DIGITAL_OCEAN_SPACE_BUCKET=... +RESEND_API_KEY=... +STRIPE_SECRET_KEY=... +STRIPE_WEBHOOK_SECRET=... +REDIS_HOST=localhost +REDIS_PORT=6379 +CLIENT_URL=http://localhost:5173 +PORT=3000 +``` + +**Client** — create `client/.env`: +``` +VITE_API_URL=http://localhost:3000 +``` + +## CI/CD + +GitHub Actions (`.github/workflows/deploy.yml`) builds Docker images and deploys to a DigitalOcean Droplet on push to `main`. Path filters ensure only changed services are rebuilt (`server/`, `scan_report/`, `scan_model/`). Images are pushed to GHCR. diff --git a/server/CLAUDE.md b/server/CLAUDE.md deleted file mode 100644 index 10d1377..0000000 --- a/server/CLAUDE.md +++ /dev/null @@ -1,156 +0,0 @@ -# TumorLens Server — CLAUDE.md - -## Stack - -- **Framework**: NestJS 11, TypeScript 5.7, Node.js 22 -- **Database**: PostgreSQL (Neon serverless, pooled via PrismaPg adapter) -- **ORM**: Prisma 7.6 -- **Auth**: JWT (Passport.js), bcrypt, otplib (2FA) -- **Email**: Resend -- **Payments**: Stripe v22 -- **File Storage**: DigitalOcean Spaces (S3-compatible via AWS SDK) -- **Events**: @nestjs/event-emitter -- **Scheduling**: @nestjs/schedule (cron jobs) -- **Validation**: class-validator + class-transformer - -## Project Structure - -``` -server/ -├── src/ -│ ├── auth/ # JWT auth, 2FA, guards, decorators, session rotation -│ ├── MriScan/ # MRI upload & ML model integration -│ ├── ScanResult/ # Scan result retrieval -│ ├── Report/ # AI-generated report management -│ ├── Patients/ # Patient CRUD -│ ├── Organization/ # Org/hospital management, API keys, audit logs -│ ├── Sessions/ # Session tracking, refresh token rotation -│ ├── Notifications/ # Email + in-app notifications, SSE stream, event listeners -│ ├── Settings/ # User profile & notification preferences -│ ├── Stripe/ # Payment processing, subscriptions -│ ├── Storage/ # DigitalOcean Spaces uploads -│ ├── Tasks/ # Scheduled background jobs -│ ├── Public-API/ # External REST API (ApiKeyGuard) -│ ├── app.module.ts -│ └── main.ts -├── prisma/ -│ ├── schema.prisma # Source of truth for all DB models -│ ├── prisma.service.ts # Prisma client with pool config (max 20 connections) -│ └── migrations/ # 70+ tracked migrations -├── test/ # E2E tests (Supertest + NestJS testing module) -├── Dockerfile # Multi-stage build (node:22-alpine) -└── .env # Local environment variables -``` - -## Conventions & Patterns - -- **Service/Controller split**: Controllers are thin (routing + parsing). All business logic lives in `.service.ts`. -- **Global route prefix**: `/api` -- **Global validation pipe**: `whitelist: true, forbidNonWhitelisted: true, transform: true` — enforced in `main.ts`. -- **DTOs**: Use `class-validator` decorators. All input must go through a DTO. -- **Events**: Use `EventEmitterModule` for async side effects (notifications, audit logs). Never call notification/audit services directly from scan/report services — emit an event instead. -- **Audit logging**: `AuditLogService` in `Organization/` tracks all org actions. Captures actor, action, category, severity, IP, user agent. -- **File uploads**: Multer `FileInterceptor`, 20MB limit for MRI scans. -- **Module naming**: PascalCase folder names (e.g. `MriScan/`, `ScanResult/`, `Public-API/`). - -## Authentication - -- **Access token**: JWT Bearer, 15-minute lifetime, secret `JWT_ACCESS_SECRET`, payload `{sub, email, role}` -- **Refresh token**: Stored hashed (bcrypt) in `Session` table, 7-day lifetime, extracted from cookie or body -- **Token rotation**: Each refresh creates a new access + refresh pair and updates the session record -- **Guards**: - - `JwtAccessGuard` — requires valid access token - - `JwtRefreshGuard` — for `/auth/refresh` - - `PlanGuard` — enforces plan tiers (FREE | DOCTOR | ORGANIZATION) - - `ApiKeyGuard` — for `Public-API` routes -- **Decorators**: - - `@RequirePlan(...plans)` — restricts endpoint by plan tier - - `@RestrictOrgMember()` — org owner only -- **2FA**: TOTP via otplib, optional per user, checked at login if enabled - -## Database Models (Key Entities) - -| Model | Notable Fields | -|-------|---------------| -| User | plan (FREE/DOCTOR/ORGANIZATION), role (USER/ADMIN), twoFactorEnabled, total_scans, total_reports | -| Organization | ownerId (unique), members (OrgMember), apiKeys, auditLogs | -| OrgMember | userId (unique), orgId, isActive | -| Patient | cin, full_name, gender, createdById, orgId | -| Scan | scan_code (unique), class (meningioma/glioma/pituitary/notumor), confidence_score, all_scores (JSON), status (PROCESSING/DONE/FAILED), processing (%) | -| ScanImage | scanId (unique), url, size, resolution, format | -| Report | content (JSON), scanId (unique), code (unique), is_shared, share_token | -| Session | userId, refreshToken (hashed), deviceInfo, ipAddress, expiresAt, isRevoked | -| Subscription | stripeCustomerId, stripeSubscriptionId, status, currentPeriodEnd | -| ApiKey | organizationId, name, key (unique), lastUsedAt | -| AuditLog | orgId, actorId, action, category, severity, ip, userAgent — indexed on (orgId, createdAt/category/status/actorEmail) | - -## Required Environment Variables - -``` -DATABASE_URL -ML_MODEL_URL -ML_MODEL_API_KEY -RAG_REPORT_URL -RAG_REPORT_API_KEY -JWT_ACCESS_SECRET -JWT_REFRESH_SECRET -DIGITAL_OCEAN_SPACE_* # bucket name, region, endpoint, access key, secret -RESEND_KEY -CLIENT_URL # e.g. http://localhost:5173 -STRIPE_SECRET_KEY -STRIPE_WEBHOOK_SECRET -ORGANIZATION_PLAN_MONTHLY # Stripe price ID -ORGANIZATION_PLAN_YEARLY -DOCTOR_PLAN_MONTHLY -DOCTOR_PLAN_YEARLY -PORT # optional, defaults to 3000 -GOOGLE_CLIENT_ID # Google OAuth app client ID -GOOGLE_CLIENT_SECRET # Google OAuth app client secret -GOOGLE_CALLBACK_URL # e.g. http://localhost:3000/api/auth/google/callback -``` - -`main.ts` calls `assertEnv()` to hard-fail on missing required vars before bootstrap. - -## Key Events (EventEmitter) - -| Event | Emitted by | Handled by | -|-------|-----------|-----------| -| `notification.send` | Various | NotificationsListener | -| `SCAN_COMPLETE` | MriScan | NotificationsListener | -| `REPORT_COMPLETE` | Report | NotificationsListener | -| `ORG_MEMBER_STATUS_CHANGE` | Organization | NotificationsListener | -| `subscription.expiring` | Tasks (cron) | NotificationsListener | - -## Running Locally - -```bash -npm install -# Set up .env with required vars -npx prisma migrate dev -npm run start:dev -``` - -## Testing - -```bash -npm test # unit tests (Jest, src/**/*.spec.ts) -npm run test:e2e # e2e tests (test/**/*.e2e-spec.ts) -npm run test:cov # coverage report -``` - -## Docker - -Multi-stage build. Builder installs deps, generates Prisma client, compiles TS. Runner copies only dist + prisma + prod deps. - -```bash -docker build -t tumorlens-server . -docker run -p 3000:3000 --env-file .env tumorlens-server -``` - -## External Services - -- **ML Model** (`ML_MODEL_URL`): Called by MriScan module to classify tumor type from MRI image -- **RAG Report** (`RAG_REPORT_URL`): Called by Report module to generate AI medical report content -- **Resend**: Transactional email via `mail.service.ts` in Notifications module -- **Stripe**: Subscriptions + one-time payments; webhook handler in Stripe module -- **DigitalOcean Spaces**: MRI image and avatar storage via S3-compatible SDK From 4492a1267ba2b916cb6330e1a2868e4014de03f1 Mon Sep 17 00:00:00 2001 From: elwessdev Date: Tue, 12 May 2026 00:56:22 +0100 Subject: [PATCH 11/30] feat: add client service with Docker configuration and nginx setup --- .gitignore | 1 + client/.dockerignore | 12 ++++++++++++ client/Dockerfile | 28 ++++++++++++++++++++++++++++ client/nginx.conf | 21 +++++++++++++++++++++ docker-compose.yml | 16 ++++++++++++++++ 5 files changed, 78 insertions(+) create mode 100644 client/.dockerignore create mode 100644 client/Dockerfile create mode 100644 client/nginx.conf diff --git a/.gitignore b/.gitignore index 5cbe69b..f003e2d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ doc *.env +RPT # compiled output */dist diff --git a/client/.dockerignore b/client/.dockerignore new file mode 100644 index 0000000..64e3522 --- /dev/null +++ b/client/.dockerignore @@ -0,0 +1,12 @@ +node_modules +dist +.env +.env.* +.git +.gitignore +.vscode +.idea +npm-debug.log +Dockerfile +.dockerignore +README.md diff --git a/client/Dockerfile b/client/Dockerfile new file mode 100644 index 0000000..c3adc5e --- /dev/null +++ b/client/Dockerfile @@ -0,0 +1,28 @@ +# ---------- Stage 1: build ---------- +FROM node:22-alpine AS builder + +WORKDIR /app + +COPY package.json package-lock.json ./ +RUN npm ci + +COPY tsconfig*.json vite.config.ts index.html ./ +COPY public ./public +COPY src ./src + +ARG VITE_API_URL +ENV VITE_API_URL=${VITE_API_URL} + +RUN npm run build + +# ---------- Stage 2: runtime ---------- +FROM nginx:1.27-alpine AS runner + +RUN rm /etc/nginx/conf.d/default.conf +COPY nginx.conf /etc/nginx/conf.d/default.conf + +COPY --from=builder /app/dist /usr/share/nginx/html + +EXPOSE 80 + +CMD ["nginx", "-g", "daemon off;"] \ No newline at end of file diff --git a/client/nginx.conf b/client/nginx.conf new file mode 100644 index 0000000..6dd99eb --- /dev/null +++ b/client/nginx.conf @@ -0,0 +1,21 @@ +server { + listen 80; + server_name _; + + root /usr/share/nginx/html; + index index.html; + + gzip on; + gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml; + gzip_min_length 1024; + + location /assets/ { + expires 1y; + add_header Cache-Control "public, immutable"; + try_files $uri =404; + } + + location / { + try_files $uri $uri/ /index.html; + } +} diff --git a/docker-compose.yml b/docker-compose.yml index 2a4c62b..d5e218f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -59,6 +59,22 @@ services: networks: - tumorlens + client: + build: + context: ./client + dockerfile: Dockerfile + args: + VITE_API_URL: ${VITE_API_URL:-http://localhost:3000} + image: tumorlens/client:latest + container_name: tumorlens_client + restart: unless-stopped + ports: + - "5173:80" + depends_on: + - server + networks: + - tumorlens + redis: image: redis:7-alpine restart: unless-stopped From dcd679b6bf7762ca0488361e2999c5cd305754b3 Mon Sep 17 00:00:00 2001 From: elwessdev Date: Tue, 12 May 2026 23:12:27 +0100 Subject: [PATCH 12/30] fix: add Redis environment variables and healthcheck to docker-compose --- docker-compose.yml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index d5e218f..12f5882 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -49,6 +49,8 @@ services: environment: ML_MODEL_URL: http://scan_model:7860 RAG_REPORT_URL: http://scan_report:8000 + REDIS_HOST: redis + REDIS_PORT: 6379 ports: - "3000:3000" depends_on: @@ -56,6 +58,8 @@ services: condition: service_healthy scan_report: condition: service_healthy + redis: + condition: service_healthy networks: - tumorlens @@ -81,9 +85,15 @@ services: volumes: - redis_data:/data ports: - - "6380:6379" + - "6379:6379" networks: - tumorlens + healthcheck: + test: ["CMD", "redis-cli", "-h", "localhost", "-p", "6379", "ping"] + interval: 10s + timeout: 5s + retries: 30 + start_period: 30s networks: tumorlens: From c6d5ac619571bf394a20be7855d875537e3f45f7 Mon Sep 17 00:00:00 2001 From: elwessdev Date: Sun, 17 May 2026 01:45:36 +0100 Subject: [PATCH 13/30] fix: remove commented-out trust badge for institutions in BrandPanel --- client/src/features/auth/shared/BrandPanel.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/features/auth/shared/BrandPanel.tsx b/client/src/features/auth/shared/BrandPanel.tsx index 3dba675..9bcd46b 100644 --- a/client/src/features/auth/shared/BrandPanel.tsx +++ b/client/src/features/auth/shared/BrandPanel.tsx @@ -76,7 +76,7 @@ export const BrandPanel = () => ( {[ // { icon: "lock", label: "HIPAA Compliant" }, { icon: "shield", label: "AES-256 Encrypted" }, - { icon: "verified", label: "450+ Institutions" }, + // { icon: "verified", label: "450+ Institutions" }, ].map(({ icon, label }) => (
Date: Wed, 20 May 2026 19:29:07 +0100 Subject: [PATCH 14/30] feat: add super admin module with services and controllers for user management, billing, and ticketing --- client/src/features/auth/google-callback.tsx | 2 +- client/src/features/auth/login.tsx | 4 +- client/src/features/auth/route.ts | 13 +- .../dashboard/Patients/AddPatientModal.tsx | 5 +- .../features/dashboard/Reports/details.tsx | 38 +- .../dashboard/ScanResults/details.tsx | 17 +- .../dashboard/components/FlagModal.tsx | 110 + client/src/features/landing/route.tsx | 8 +- .../features/superadmin/api/superadmin.api.ts | 327 ++ .../superadmin/components/AreaChart.tsx | 271 ++ .../superadmin/components/KPICard.tsx | 57 + .../components/SuperAdminLayout.tsx | 209 ++ .../superadmin/components/UserDetailModal.tsx | 169 + .../UserDetailTabs/OrganizationTab.tsx | 134 + .../components/UserDetailTabs/PatientsTab.tsx | 61 + .../components/UserDetailTabs/ProfileTab.tsx | 77 + .../components/UserDetailTabs/ReportsTab.tsx | 73 + .../components/UserDetailTabs/ScansTab.tsx | 82 + client/src/features/superadmin/route.ts | 59 + .../features/superadmin/routes/audit-logs.tsx | 192 ++ .../features/superadmin/routes/billing.tsx | 265 ++ .../src/features/superadmin/routes/index.tsx | 513 +++ .../superadmin/routes/tickets-detail.tsx | 297 ++ .../features/superadmin/routes/tickets.tsx | 153 + .../src/features/superadmin/routes/users.tsx | 157 + client/src/router.ts | 17 + server/prisma/generated/client/browser.ts | 5 + server/prisma/generated/client/client.ts | 5 + .../generated/client/commonInputTypes.ts | 102 + server/prisma/generated/client/enums.ts | 29 +- .../prisma/generated/client/internal/class.ts | 18 +- .../client/internal/prismaNamespace.ts | 142 +- .../client/internal/prismaNamespaceBrowser.ts | 23 + server/prisma/generated/client/models.ts | 1 + .../generated/client/models/AuditLog.ts | 79 +- .../generated/client/models/Organization.ts | 4 +- .../prisma/generated/client/models/Report.ts | 294 ++ server/prisma/generated/client/models/Scan.ts | 379 +++ .../prisma/generated/client/models/Ticket.ts | 2767 +++++++++++++++++ server/prisma/generated/client/models/User.ts | 494 +++ .../migration.sql | 66 + .../migration.sql | 2 + server/prisma/schema.prisma | 67 +- .../Notifications/notifications.listener.ts | 36 +- server/src/Organization/audit-log.service.ts | 163 + server/src/Report/report.controller.ts | 23 + server/src/Report/report.service.ts | 60 +- .../src/ScanResult/scan_result.controller.ts | 24 + server/src/ScanResult/scan_result.service.ts | 55 +- .../controllers/audit.controller.ts | 29 + .../controllers/billing.controller.ts | 43 + .../controllers/overview.controller.ts | 15 + .../controllers/tickets.controller.ts | 60 + .../controllers/users.controller.ts | 67 + .../decorators/require-role.decorator.ts | 6 + server/src/SuperAdmin/dto/billing.dto.ts | 30 + server/src/SuperAdmin/dto/list-users.dto.ts | 53 + server/src/SuperAdmin/dto/ticket.dto.ts | 67 + .../SuperAdmin/dto/update-user-status.dto.ts | 6 + .../SuperAdmin/guards/super-admin.guard.ts | 44 + .../SuperAdmin/services/billing.service.ts | 159 + .../SuperAdmin/services/overview.service.ts | 153 + .../SuperAdmin/services/tickets.service.ts | 398 +++ .../src/SuperAdmin/services/users.service.ts | 297 ++ server/src/SuperAdmin/super-admin.module.ts | 39 + server/src/app.module.ts | 4 +- 66 files changed, 9553 insertions(+), 65 deletions(-) create mode 100644 client/src/features/dashboard/components/FlagModal.tsx create mode 100644 client/src/features/superadmin/api/superadmin.api.ts create mode 100644 client/src/features/superadmin/components/AreaChart.tsx create mode 100644 client/src/features/superadmin/components/KPICard.tsx create mode 100644 client/src/features/superadmin/components/SuperAdminLayout.tsx create mode 100644 client/src/features/superadmin/components/UserDetailModal.tsx create mode 100644 client/src/features/superadmin/components/UserDetailTabs/OrganizationTab.tsx create mode 100644 client/src/features/superadmin/components/UserDetailTabs/PatientsTab.tsx create mode 100644 client/src/features/superadmin/components/UserDetailTabs/ProfileTab.tsx create mode 100644 client/src/features/superadmin/components/UserDetailTabs/ReportsTab.tsx create mode 100644 client/src/features/superadmin/components/UserDetailTabs/ScansTab.tsx create mode 100644 client/src/features/superadmin/route.ts create mode 100644 client/src/features/superadmin/routes/audit-logs.tsx create mode 100644 client/src/features/superadmin/routes/billing.tsx create mode 100644 client/src/features/superadmin/routes/index.tsx create mode 100644 client/src/features/superadmin/routes/tickets-detail.tsx create mode 100644 client/src/features/superadmin/routes/tickets.tsx create mode 100644 client/src/features/superadmin/routes/users.tsx create mode 100644 server/prisma/generated/client/models/Ticket.ts create mode 100644 server/prisma/migrations/20260520164706_super_admin_and_tickets/migration.sql create mode 100644 server/prisma/migrations/20260520172537_audit_log_org_nullable/migration.sql create mode 100644 server/src/SuperAdmin/controllers/audit.controller.ts create mode 100644 server/src/SuperAdmin/controllers/billing.controller.ts create mode 100644 server/src/SuperAdmin/controllers/overview.controller.ts create mode 100644 server/src/SuperAdmin/controllers/tickets.controller.ts create mode 100644 server/src/SuperAdmin/controllers/users.controller.ts create mode 100644 server/src/SuperAdmin/decorators/require-role.decorator.ts create mode 100644 server/src/SuperAdmin/dto/billing.dto.ts create mode 100644 server/src/SuperAdmin/dto/list-users.dto.ts create mode 100644 server/src/SuperAdmin/dto/ticket.dto.ts create mode 100644 server/src/SuperAdmin/dto/update-user-status.dto.ts create mode 100644 server/src/SuperAdmin/guards/super-admin.guard.ts create mode 100644 server/src/SuperAdmin/services/billing.service.ts create mode 100644 server/src/SuperAdmin/services/overview.service.ts create mode 100644 server/src/SuperAdmin/services/tickets.service.ts create mode 100644 server/src/SuperAdmin/services/users.service.ts create mode 100644 server/src/SuperAdmin/super-admin.module.ts diff --git a/client/src/features/auth/google-callback.tsx b/client/src/features/auth/google-callback.tsx index e2fd926..766a165 100644 --- a/client/src/features/auth/google-callback.tsx +++ b/client/src/features/auth/google-callback.tsx @@ -32,7 +32,7 @@ export const GoogleCallbackPage = () => { data.notificationSettings ); navigate({ - to: "/" + to: data.user?.role === "SUPER_ADMIN" ? "/superadmin" : "/" }); }) .catch(() => navigate({ to: "/login" })); diff --git a/client/src/features/auth/login.tsx b/client/src/features/auth/login.tsx index ac3da9a..3119b2f 100644 --- a/client/src/features/auth/login.tsx +++ b/client/src/features/auth/login.tsx @@ -27,7 +27,7 @@ export const LoginPage = () => { return; } setAuth(data.accessToken, data.user, data.notificationSettings); - navigate({ to: "/" }); + navigate({ to: data.user?.role === "SUPER_ADMIN" ? "/superadmin" : "/" }); }, onError: error => { const e = error as { response?: { data?: { message?: string } } }; @@ -46,7 +46,7 @@ export const LoginPage = () => { onSuccess: data => { if (data?.twoFactorRequired) return; setAuth(data.accessToken, data.user, data.notificationSettings); - navigate({ to: "/" }); + navigate({ to: data.user?.role === "SUPER_ADMIN" ? "/superadmin" : "/" }); }, onError: error => { const e = error as { response?: { data?: { message?: string } } }; diff --git a/client/src/features/auth/route.ts b/client/src/features/auth/route.ts index 40d3a3b..79b7589 100644 --- a/client/src/features/auth/route.ts +++ b/client/src/features/auth/route.ts @@ -7,12 +7,17 @@ import { ForgotPasswordPage } from "./forgot-password"; import { ResetPasswordPage } from "./reset-password"; import { GoogleCallbackPage } from "./google-callback"; +const homeForRole = () => { + const { user } = useAuthStore.getState(); + return user?.role === "SUPER_ADMIN" ? "/superadmin" : "/"; +}; + // Register page route export const RegisterPageRoute = createRoute({ getParentRoute: () => rootRoute, path: "/register", beforeLoad: () => { - if (useAuthStore.getState().accessToken) throw redirect({ to: '/dashboard' }); + if (useAuthStore.getState().accessToken) throw redirect({ to: homeForRole() }); }, component: RegisterPage, }); @@ -22,7 +27,7 @@ export const LoginPageRoute = createRoute({ getParentRoute: () => rootRoute, path: "/login", beforeLoad: () => { - if (useAuthStore.getState().accessToken) throw redirect({ to: '/' }); + if (useAuthStore.getState().accessToken) throw redirect({ to: homeForRole() }); }, component: LoginPage, }); @@ -32,7 +37,7 @@ export const ForgotPasswordPageRoute = createRoute({ getParentRoute: () => rootRoute, path: "/forgot-password", beforeLoad: () => { - if (useAuthStore.getState().accessToken) throw redirect({ to: '/' }); + if (useAuthStore.getState().accessToken) throw redirect({ to: homeForRole() }); }, component: ForgotPasswordPage, }); @@ -45,7 +50,7 @@ export const ResetPasswordPageRoute = createRoute({ token: typeof search.token === "string" ? search.token : "", }), beforeLoad: () => { - if (useAuthStore.getState().accessToken) throw redirect({ to: '/' }); + if (useAuthStore.getState().accessToken) throw redirect({ to: homeForRole() }); }, component: ResetPasswordPage, }); diff --git a/client/src/features/dashboard/Patients/AddPatientModal.tsx b/client/src/features/dashboard/Patients/AddPatientModal.tsx index 056edd7..b7a354b 100644 --- a/client/src/features/dashboard/Patients/AddPatientModal.tsx +++ b/client/src/features/dashboard/Patients/AddPatientModal.tsx @@ -131,7 +131,10 @@ export const AddPatientModal = ({open,cancel,mode,pData}: Props) => {
- + !!d && d.isAfter(dayjs().endOf("day"))} + /> +
+
+ + ); +}; diff --git a/client/src/features/landing/route.tsx b/client/src/features/landing/route.tsx index d733307..c80d9eb 100644 --- a/client/src/features/landing/route.tsx +++ b/client/src/features/landing/route.tsx @@ -1,9 +1,15 @@ -import { createRoute } from "@tanstack/react-router"; +import { createRoute, redirect } from "@tanstack/react-router"; import { rootRoute } from "../../rootRoute"; +import { useAuthStore } from "../../store/auth.store"; import { IndexPage } from "."; export const AppLayoutRoute = createRoute({ getParentRoute: () => rootRoute, id: "app-layout", + beforeLoad: () => { + if (useAuthStore.getState().user?.role === "SUPER_ADMIN") { + throw redirect({ to: "/superadmin" }); + } + }, component: IndexPage }); \ No newline at end of file diff --git a/client/src/features/superadmin/api/superadmin.api.ts b/client/src/features/superadmin/api/superadmin.api.ts new file mode 100644 index 0000000..29ba3d2 --- /dev/null +++ b/client/src/features/superadmin/api/superadmin.api.ts @@ -0,0 +1,327 @@ +import axios from "../../../lib/axios"; + +export type OverviewResponse = { + totalUsers: number; + usersDelta7d: number; + activeSubscriptions: { doctor: number; org: number }; + scansProcessed: { today: number; last7d: number; last30d: number }; + reportsGenerated: { today: number; last7d: number; last30d: number }; + mrr: number; + openTicketsCount: number; + signups30d: { date: string; count: number }[]; + scansPerDay30d: { date: string; count: number }[]; + planDistribution: { free: number; doctor: number; org: number }; + recentSignups: Array<{ + id: string; + username: string; + email: string; + plan: string; + role: string; + profile_image_url: string | null; + createdAt: string; + }>; + recentTickets: Array<{ + id: string; + code: string; + type: string; + status: string; + priority: string; + reason: string; + createdAt: string; + submittedBy: { id: string; username: string; email: string }; + }>; +}; + +export type UserListItem = { + id: string; + username: string; + email: string; + role: string; + plan: string; + is_active: boolean; + profile_image_url: string | null; + total_scans: number; + total_reports: number; + createdAt: string; + ownedOrg: { id: string; name: string } | null; + orgMember: { id: string; orgId: string } | null; +}; + +export type Paginated = { items: T[]; total: number; page: number; pageSize: number }; + +export type UserProfile = { + id: string; + username: string; + email: string; + role: string; + plan: string; + is_active: boolean; + profile_image_url: string | null; + total_scans: number; + total_reports: number; + twoFactorEnabled: boolean; + createdAt: string; + updatedAt: string; + ownedOrg: { id: string; name: string; createdAt: string } | null; + orgMember: { id: string; isActive: boolean; org: { id: string; name: string } } | null; + subscription: { + status: string; + currentPeriodEnd: string; + cancelAtPeriodEnd: boolean; + stripeSubscriptionId: string; + } | null; +}; + +export type ListUsersParams = { + plan?: string; + role?: string; + status?: "active" | "inactive"; + hasOrg?: "true" | "false"; + q?: string; + page?: number; + pageSize?: number; +}; + +export type Subscription = { + id: string; + stripeCustomerId: string; + stripeSubscriptionId: string; + status: string; + currentPeriodEnd: string; + cancelAtPeriodEnd: boolean; + createdAt: string; + user: { + id: string; + username: string; + email: string; + plan: string; + profile_image_url: string | null; + }; +}; + +export type BillingKPIs = { + activeDoctor: number; + activeOrg: number; + pastDue: number; + canceled: number; + mrr: number; +}; + +export type Payment = { + id: string; + amount: number; + status: string; + stripePaymentId: string; + plan: string; + mode: string; + createdAt: string; + user: { id: string; username: string; email: string }; +}; + +export type AuditLogItem = { + id: string; + orgId: string | null; + organization: { id: string; name: string } | null; + actorId: string | null; + actorName: string; + actorEmail: string; + action: string; + category: string; + status: string; + severity: string; + target: string; + targetId: string | null; + ip: string | null; + userAgent: string | null; + createdAt: string; +}; + +export type TicketListItem = { + id: string; + code: string; + type: "RE_ANALYSIS" | "RE_REPORT"; + status: "OPEN" | "IN_PROGRESS" | "RESOLVED" | "DISMISSED"; + priority: "LOW" | "MEDIUM" | "HIGH"; + reason: string; + createdAt: string; + updatedAt: string; + resolvedAt: string | null; + submittedBy: { id: string; username: string; email: string; profile_image_url: string | null }; + assignedTo: { id: string; username: string; email: string } | null; + scan: { id: string; scan_code: string; class: string } | null; + report: { id: string; code: string } | null; +}; + +export type TicketDetail = TicketListItem & { + resolutionNote: string | null; + reanalysisScan: { id: string; scan_code: string; class: string; confidence_score: number } | null; + reanalysisReport: { id: string; code: string } | null; + submittedBy: TicketListItem["submittedBy"] & { plan: string }; + scan: (TicketListItem["scan"] & { + patient: { id: string; full_name: string } | null; + scanImage: { id: string; url: string; size: number; resolution: string; format: string; name: string } | null; + report: { id: string; code: string } | null; + }) | null; + report: (TicketListItem["report"] & { + scanId: string; + content: unknown; + scan: { id: string; scan_code: string; patient: { id: string; full_name: string } | null }; + }) | null; +}; + +// Overview +export const getOverview = async (): Promise => { + const { data } = await axios.get("/superadmin/overview"); + return data; +}; + +// Users +export const listUsers = async (params: ListUsersParams): Promise> => { + const { data } = await axios.get>("/superadmin/users", { params }); + return data; +}; + +export const getUserProfile = async (id: string): Promise => { + const { data } = await axios.get(`/superadmin/users/${id}`); + return data; +}; + +export const getUserScans = async (id: string, page = 1, pageSize = 20) => { + const { data } = await axios.get(`/superadmin/users/${id}/scans`, { + params: { page, pageSize }, + }); + return data; +}; + +export const getUserReports = async (id: string, page = 1, pageSize = 20) => { + const { data } = await axios.get(`/superadmin/users/${id}/reports`, { + params: { page, pageSize }, + }); + return data; +}; + +export const getUserPatients = async (id: string, page = 1, pageSize = 20) => { + const { data } = await axios.get(`/superadmin/users/${id}/patients`, { + params: { page, pageSize }, + }); + return data; +}; + +export const getUserOrganization = async (id: string) => { + const { data } = await axios.get(`/superadmin/users/${id}/organization`); + return data; +}; + +export const setUserStatus = async (id: string, isActive: boolean) => { + const { data } = await axios.patch(`/superadmin/users/${id}/status`, { is_active: isActive }); + return data; +}; + +export const forceResetUser = async (id: string) => { + const { data } = await axios.post(`/superadmin/users/${id}/force-reset`); + return data as { success: boolean; resetToken: string; expiresAt: string }; +}; + +export const deleteUser = async (id: string) => { + const { data } = await axios.delete(`/superadmin/users/${id}`); + return data; +}; + +// Billing +export const getBillingKpis = async (): Promise => { + const { data } = await axios.get("/superadmin/billing/kpis"); + return data; +}; + +export const listSubscriptions = async (params: { + status?: string; + plan?: string; + q?: string; + page?: number; + pageSize?: number; +}): Promise> => { + const { data } = await axios.get>("/superadmin/billing/subscriptions", { params }); + return data; +}; + +export const syncSubscription = async (stripeSubscriptionId: string) => { + const { data } = await axios.post(`/superadmin/billing/subscriptions/${stripeSubscriptionId}/sync`); + return data; +}; + +export const cancelSubscription = async (stripeSubscriptionId: string) => { + const { data } = await axios.post(`/superadmin/billing/subscriptions/${stripeSubscriptionId}/cancel`); + return data; +}; + +export const recentPayments = async (limit = 20): Promise => { + const { data } = await axios.get("/superadmin/billing/payments", { params: { limit } }); + return data; +}; + +// Audit Logs +export const listAuditLogs = async (params: { + search?: string; + category?: string; + status?: string; + from?: string; + to?: string; + page?: number; + pageSize?: number; +}): Promise> => { + const { data } = await axios.get>("/superadmin/audit-logs", { params }); + return data; +}; + +export const exportAuditLogs = async (params: Record) => { + const search = new URLSearchParams(); + Object.entries(params).forEach(([k, v]) => { + if (v !== undefined && v !== null && v !== "") search.append(k, String(v)); + }); + const base = (axios.defaults.baseURL ?? "").replace(/\/$/, ""); + const url = `${base}/superadmin/audit-logs/export?${search.toString()}`; + window.open(url, "_blank"); +}; + +// Tickets +export const listTickets = async (params: { + status?: string; + type?: string; + priority?: string; + q?: string; + page?: number; + pageSize?: number; +}): Promise> => { + const { data } = await axios.get>("/superadmin/tickets", { params }); + return data; +}; + +export const getTicket = async (code: string): Promise => { + const { data } = await axios.get(`/superadmin/tickets/${code}`); + return data; +}; + +export const assignTicket = async (code: string, assignedToId: string) => { + const { data } = await axios.patch(`/superadmin/tickets/${code}/assign`, { assignedToId }); + return data; +}; + +export const reanalyzeTicket = async (code: string) => { + const { data } = await axios.post(`/superadmin/tickets/${code}/reanalyze`); + return data; +}; + +export const regenerateTicket = async (code: string) => { + const { data } = await axios.post(`/superadmin/tickets/${code}/regenerate`); + return data; +}; + +export const resolveTicket = async (code: string, resolutionNote: string) => { + const { data } = await axios.patch(`/superadmin/tickets/${code}/resolve`, { resolutionNote }); + return data; +}; + +export const dismissTicket = async (code: string, resolutionNote?: string) => { + const { data } = await axios.patch(`/superadmin/tickets/${code}/dismiss`, { resolutionNote }); + return data; +}; diff --git a/client/src/features/superadmin/components/AreaChart.tsx b/client/src/features/superadmin/components/AreaChart.tsx new file mode 100644 index 0000000..6ace9f3 --- /dev/null +++ b/client/src/features/superadmin/components/AreaChart.tsx @@ -0,0 +1,271 @@ +import { useMemo, useState, useRef } from "react"; + +type Point = { date: string; count: number }; + +type Props = { + data: Point[]; + color?: string; + height?: number; + label?: string; + valueLabel?: string; +}; + +const PAD = { top: 18, right: 14, bottom: 26, left: 36 }; +const W = 600; + +const niceMax = (raw: number) => { + if (raw <= 1) return 1; + const pow = Math.pow(10, Math.floor(Math.log10(raw))); + const norm = raw / pow; + let nice; + if (norm <= 1) nice = 1; + else if (norm <= 2) nice = 2; + else if (norm <= 5) nice = 5; + else nice = 10; + return nice * pow; +}; + +const fmtTick = (d: string) => { + const dt = new Date(d); + return `${dt.getUTCMonth() + 1}/${dt.getUTCDate()}`; +}; + +export const AreaChart = ({ + data, + color = "#2563eb", + height = 240, + valueLabel = "value", +}: Props) => { + const containerRef = useRef(null); + const [hoverIdx, setHoverIdx] = useState(null); + + const { yMax, yTicks, xPositions, areaPath, linePath, total, peak } = useMemo(() => { + const counts = data.map((d) => d.count); + const rawMax = Math.max(...counts, 1); + const yMax = niceMax(rawMax); + const innerW = W - PAD.left - PAD.right; + const innerH = height - PAD.top - PAD.bottom; + + const xPositions = data.map((_, i) => + data.length === 1 ? PAD.left + innerW / 2 : PAD.left + (i * innerW) / (data.length - 1), + ); + const yFor = (v: number) => PAD.top + innerH - (v / yMax) * innerH; + const points = data.map((d, i) => [xPositions[i], yFor(d.count)] as const); + + const linePath = points.map((p, i) => `${i === 0 ? "M" : "L"}${p[0].toFixed(1)},${p[1].toFixed(1)}`).join(" "); + const baselineY = PAD.top + innerH; + const areaPath = `${linePath} L${points[points.length - 1][0].toFixed(1)},${baselineY} L${points[0][0].toFixed(1)},${baselineY} Z`; + + const yTicks = [0, 0.25, 0.5, 0.75, 1].map((f) => ({ + y: yFor(yMax * f), + value: Math.round(yMax * f), + })); + + const total = counts.reduce((s, c) => s + c, 0); + const peakIdx = counts.indexOf(Math.max(...counts)); + const peak = { idx: peakIdx, count: counts[peakIdx], date: data[peakIdx]?.date }; + + return { yMax, yTicks, xPositions, areaPath, linePath, total, peak }; + }, [data, height]); + + const xTickIndexes = useMemo(() => { + if (data.length <= 6) return data.map((_, i) => i); + const step = Math.floor((data.length - 1) / 5); + const idxs = []; + for (let i = 0; i < data.length; i += step) idxs.push(i); + if (idxs[idxs.length - 1] !== data.length - 1) idxs.push(data.length - 1); + return idxs; + }, [data]); + + const onMouseMove = (e: React.MouseEvent) => { + const svg = e.currentTarget; + const rect = svg.getBoundingClientRect(); + const x = ((e.clientX - rect.left) / rect.width) * W; + let nearest = 0; + let minDist = Infinity; + for (let i = 0; i < xPositions.length; i++) { + const d = Math.abs(xPositions[i] - x); + if (d < minDist) { + minDist = d; + nearest = i; + } + } + setHoverIdx(nearest); + }; + + const hoverPoint = hoverIdx !== null && data[hoverIdx] + ? { + x: xPositions[hoverIdx], + y: PAD.top + (height - PAD.top - PAD.bottom) - (data[hoverIdx].count / yMax) * (height - PAD.top - PAD.bottom), + data: data[hoverIdx], + } + : null; + + const gradientId = `area-grad-${color.replace("#", "")}`; + + return ( +
+
+
+ + {total.toLocaleString()} + + total +
+ {peak.count > 0 && ( +
+ + {peak.count} + + + peak · {peak.date ? fmtTick(peak.date) : ""} + +
+ )} +
+ + setHoverIdx(null)} + > + + + + + + + + {/* gridlines + Y labels */} + {yTicks.map((t) => ( + + + + {t.value} + + + ))} + + {/* area + line */} + + + + {/* peak marker */} + {peak.count > 0 && ( + + )} + + {/* X-axis labels */} + {xTickIndexes.map((i) => ( + + {fmtTick(data[i].date)} + + ))} + + {/* hover crosshair */} + {hoverPoint && ( + <> + + + + )} + + + {hoverPoint && ( +
+
+ {new Date(hoverPoint.data.date).toLocaleDateString(undefined, { + month: "short", + day: "numeric", + year: "numeric", + })} +
+
+ {hoverPoint.data.count} {valueLabel} +
+
+ )} +
+ ); +}; diff --git a/client/src/features/superadmin/components/KPICard.tsx b/client/src/features/superadmin/components/KPICard.tsx new file mode 100644 index 0000000..5136dd1 --- /dev/null +++ b/client/src/features/superadmin/components/KPICard.tsx @@ -0,0 +1,57 @@ +import { Card } from "antd"; +import type { ReactNode } from "react"; + +type Props = { + label: string; + value: ReactNode; + sub?: ReactNode; + accent?: string; + icon?: ReactNode; +}; + +export const KPICard = ({ label, value, sub, accent = "#004ac6", icon }: Props) => ( + +
+
+
+ {label} +
+
+ {value} +
+ {sub && ( +
{sub}
+ )} +
+ {icon && ( +
+ {icon} +
+ )} +
+
+); diff --git a/client/src/features/superadmin/components/SuperAdminLayout.tsx b/client/src/features/superadmin/components/SuperAdminLayout.tsx new file mode 100644 index 0000000..917f4df --- /dev/null +++ b/client/src/features/superadmin/components/SuperAdminLayout.tsx @@ -0,0 +1,209 @@ +import { Outlet, Link, useRouterState } from "@tanstack/react-router"; +import { useAuthStore } from "../../../store/auth.store"; +import { + MdSpaceDashboard, + MdPeopleAlt, + MdAttachMoney, + MdReceiptLong, + MdSupportAgent, + MdLogout, +} from "react-icons/md"; +import { message } from "antd"; +import { useLogout } from "../../auth/hooks"; + +type NavItem = { to: string; label: string; Icon: React.ComponentType<{ size?: number; color?: string }>; exact?: boolean }; +const NAV: NavItem[] = [ + { to: "/superadmin", label: "Overview", Icon: MdSpaceDashboard, exact: true }, + { to: "/superadmin/users", label: "Users", Icon: MdPeopleAlt }, + { to: "/superadmin/billing", label: "Billing", Icon: MdAttachMoney }, + { to: "/superadmin/audit-logs", label: "Audit Logs", Icon: MdReceiptLong }, + { to: "/superadmin/tickets", label: "Tickets", Icon: MdSupportAgent }, +]; + +export const SuperAdminLayout = () => { + const currentPath = useRouterState({ select: (s) => s.location.pathname }); + const user = useAuthStore((s) => s.user); + const clear = useAuthStore((s) => s.clear); + const { mutate: logout } = useLogout(); + + const handleLogout = () => { + logout(undefined, { + onSuccess: () => { + message.success("Logged out"); + clear(); + }, + }); + }; + + return ( +
+ + +
+
+
+ Super Admin Console +
+
+
+ {user?.profile_image_url ? ( + + ) : ( + user?.username?.slice(0, 2).toUpperCase() ?? "SA" + )} +
+
+
{user?.username}
+
{user?.email}
+
+
+
+ +
+ +
+
+
+ ); +}; diff --git a/client/src/features/superadmin/components/UserDetailModal.tsx b/client/src/features/superadmin/components/UserDetailModal.tsx new file mode 100644 index 0000000..10cece8 --- /dev/null +++ b/client/src/features/superadmin/components/UserDetailModal.tsx @@ -0,0 +1,169 @@ +import { useMemo, useState } from "react"; +import { Modal, Tabs, Dropdown, Button, Popconfirm, message } from "antd"; +import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; +import { MdMoreVert } from "react-icons/md"; +import { + getUserProfile, + setUserStatus, + forceResetUser, + deleteUser, + getUserPatients, +} from "../api/superadmin.api"; +import { ProfileTab } from "./UserDetailTabs/ProfileTab"; +import { ScansTab } from "./UserDetailTabs/ScansTab"; +import { ReportsTab } from "./UserDetailTabs/ReportsTab"; +import { PatientsTab } from "./UserDetailTabs/PatientsTab"; +import { OrganizationTab } from "./UserDetailTabs/OrganizationTab"; + +type Props = { + open: boolean; + userId: string | null; + onClose: () => void; +}; + +export const UserDetailModal = ({ open, userId, onClose }: Props) => { + const qc = useQueryClient(); + const [activeKey, setActiveKey] = useState("profile"); + + const profileQ = useQuery({ + queryKey: ["superadmin", "user", userId, "profile"], + queryFn: () => getUserProfile(userId!), + enabled: !!userId && open, + }); + + const profile = profileQ.data; + + // Probe whether DOCTOR user has patients (cheap — just need count > 0) + const patientsProbe = useQuery({ + queryKey: ["superadmin", "user", userId, "patients-probe"], + queryFn: () => getUserPatients(userId!, 1, 1), + enabled: !!userId && open && profile?.plan === "DOCTOR", + }); + + const showPatients = profile?.plan === "DOCTOR" && (patientsProbe.data?.total ?? 0) > 0; + const showOrg = profile?.plan === "ORGANIZATION" && !!profile?.ownedOrg; + + const tabs = useMemo(() => { + if (!userId) return []; + const base = [ + { key: "profile", label: "Profile", children: }, + { key: "scans", label: "Scans", children: }, + { key: "reports", label: "Reports", children: }, + ]; + if (showPatients) { + base.push({ key: "patients", label: "Patients", children: }); + } + if (showOrg) { + base.push({ key: "organization", label: "Organization", children: }); + } + return base; + }, [userId, showPatients, showOrg]); + + const statusMut = useMutation({ + mutationFn: ({ active }: { active: boolean }) => setUserStatus(userId!, active), + onSuccess: (_, { active }) => { + message.success(active ? "User activated" : "User deactivated"); + qc.invalidateQueries({ queryKey: ["superadmin", "user", userId] }); + qc.invalidateQueries({ queryKey: ["superadmin", "users"] }); + }, + onError: (err: unknown) => { + const e = err as { response?: { data?: { message?: string } } }; + message.error(e.response?.data?.message ?? "Action failed"); + }, + }); + + const resetMut = useMutation({ + mutationFn: () => forceResetUser(userId!), + onSuccess: (data) => { + Modal.info({ + title: "Reset token issued", + content: ( +
+

Share this reset link with the user (valid for 1 hour):

+ + /reset-password?token={data.resetToken} + +
+ ), + width: 560, + }); + }, + onError: (err: unknown) => { + const e = err as { response?: { data?: { message?: string } } }; + message.error(e.response?.data?.message ?? "Action failed"); + }, + }); + + const deleteMut = useMutation({ + mutationFn: () => deleteUser(userId!), + onSuccess: () => { + message.success("User deleted"); + qc.invalidateQueries({ queryKey: ["superadmin", "users"] }); + onClose(); + }, + onError: (err: unknown) => { + const e = err as { response?: { data?: { message?: string } } }; + message.error(e.response?.data?.message ?? "Action failed"); + }, + }); + + const actionMenu = { + items: [ + { + key: "status", + label: profile?.is_active ? "Deactivate user" : "Activate user", + }, + { key: "reset", label: "Force password reset" }, + { type: "divider" as const }, + { key: "delete", label: Delete user, danger: true }, + ], + onClick: ({ key }: { key: string }) => { + if (key === "status") statusMut.mutate({ active: !profile?.is_active }); + if (key === "reset") resetMut.mutate(); + if (key === "delete") { + Modal.confirm({ + title: "Delete user?", + content: "This soft-deletes the user (deactivates + scrambles credentials). This cannot be undone.", + okType: "danger", + okText: "Delete", + onOk: () => deleteMut.mutateAsync(), + }); + } + }, + }; + + // Suppress unused Popconfirm import warning by keeping it available for future use + void Popconfirm; + + return ( + +
+
+ {profile?.username ?? "User detail"} +
+
{profile?.email}
+
+ {profile && ( + + + + )} +

+ } + > + + + ); +}; diff --git a/client/src/features/superadmin/components/UserDetailTabs/OrganizationTab.tsx b/client/src/features/superadmin/components/UserDetailTabs/OrganizationTab.tsx new file mode 100644 index 0000000..5ad12b6 --- /dev/null +++ b/client/src/features/superadmin/components/UserDetailTabs/OrganizationTab.tsx @@ -0,0 +1,134 @@ +import { useQuery } from "@tanstack/react-query"; +import { Skeleton, Table, Tag, Avatar, Empty, Divider } from "antd"; +import { getUserOrganization } from "../../api/superadmin.api"; + +type OrgResponse = { + id: string; + name: string; + createdAt: string; + members: Array<{ + id: string; + isActive: boolean; + user: { id: string; username: string; email: string; profile_image_url: string | null; is_active: boolean }; + }>; + patients: Array<{ + id: string; + cin: string; + full_name: string; + gender: string; + createdAt: string; + _count: { scans: number }; + }>; + apiKeys: Array<{ + id: string; + name: string; + key: string; + lastUsedAt: string | null; + createdAt: string; + }>; +}; + +export const OrganizationTab = ({ userId }: { userId: string }) => { + const { data, isLoading } = useQuery({ + queryKey: ["superadmin", "user", userId, "organization"], + queryFn: () => getUserOrganization(userId) as Promise, + }); + + if (isLoading) return ; + if (!data) return ; + + return ( +
+
+
{data.name}
+
+ Created {new Date(data.createdAt).toLocaleDateString()} · {data.members.length} members ·{" "} + {data.patients.length} patients · {data.apiKeys.length} API keys +
+
+ +
Members
+ + ( +
+ + {r.user.username.slice(0, 2).toUpperCase()} + + {r.user.username} +
+ ), + }, + { title: "Email", dataIndex: ["user", "email"] }, + { + title: "Status", + render: (_: unknown, r: OrgResponse["members"][number]) => ( + + {r.isActive && r.user.is_active ? "Active" : "Inactive"} + + ), + }, + ]} + /> + +
Patients
+ +
{v}, + }, + { + title: "Scans", + dataIndex: ["_count", "scans"], + render: (_: unknown, r: OrgResponse["patients"][number]) => r._count.scans, + }, + ]} + /> + +
API Keys
+ +
( + {v.slice(0, 18)}… + ), + }, + { + title: "Last used", + dataIndex: "lastUsedAt", + render: (v: string | null) => (v ? new Date(v).toLocaleDateString() : "—"), + }, + { + title: "Created", + dataIndex: "createdAt", + render: (v: string) => new Date(v).toLocaleDateString(), + }, + ]} + /> + + ); +}; diff --git a/client/src/features/superadmin/components/UserDetailTabs/PatientsTab.tsx b/client/src/features/superadmin/components/UserDetailTabs/PatientsTab.tsx new file mode 100644 index 0000000..df9341c --- /dev/null +++ b/client/src/features/superadmin/components/UserDetailTabs/PatientsTab.tsx @@ -0,0 +1,61 @@ +import { useState } from "react"; +import { useQuery } from "@tanstack/react-query"; +import { Table, Tag } from "antd"; +import { getUserPatients } from "../../api/superadmin.api"; + +type PatientRow = { + id: string; + cin: string; + full_name: string; + gender: string; + email: string; + phone_number: string; + createdAt: string; + _count: { scans: number }; +}; + +export const PatientsTab = ({ userId }: { userId: string }) => { + const [page, setPage] = useState(1); + const pageSize = 10; + const { data, isLoading } = useQuery({ + queryKey: ["superadmin", "user", userId, "patients", page], + queryFn: () => getUserPatients(userId, page, pageSize), + }); + + return ( + + dataSource={data?.items ?? []} + rowKey="id" + loading={isLoading} + size="small" + pagination={{ + current: page, + pageSize, + total: data?.total ?? 0, + onChange: setPage, + showSizeChanger: false, + }} + columns={[ + { title: "CIN", dataIndex: "cin" }, + { title: "Name", dataIndex: "full_name" }, + { + title: "Gender", + dataIndex: "gender", + render: (v: string) => {v}, + }, + { title: "Email", dataIndex: "email" }, + { title: "Phone", dataIndex: "phone_number" }, + { + title: "Scans", + dataIndex: ["_count", "scans"], + render: (_: unknown, r: PatientRow) => r._count.scans, + }, + { + title: "Created", + dataIndex: "createdAt", + render: (v: string) => new Date(v).toLocaleDateString(), + }, + ]} + /> + ); +}; diff --git a/client/src/features/superadmin/components/UserDetailTabs/ProfileTab.tsx b/client/src/features/superadmin/components/UserDetailTabs/ProfileTab.tsx new file mode 100644 index 0000000..75f827e --- /dev/null +++ b/client/src/features/superadmin/components/UserDetailTabs/ProfileTab.tsx @@ -0,0 +1,77 @@ +import { useQuery } from "@tanstack/react-query"; +import { Skeleton, Tag, Avatar, Descriptions } from "antd"; +import { getUserProfile } from "../../api/superadmin.api"; + +export const ProfileTab = ({ userId }: { userId: string }) => { + const { data, isLoading } = useQuery({ + queryKey: ["superadmin", "user", userId, "profile"], + queryFn: () => getUserProfile(userId), + }); + + if (isLoading || !data) return ; + + return ( +
+
+ + {data.username.slice(0, 2).toUpperCase()} + +
+
{data.username}
+
{data.email}
+
+ + {data.plan} + + + {data.role} + + + {data.is_active ? "Active" : "Inactive"} + + {data.twoFactorEnabled && 2FA} +
+
+
+ + + {data.id} + {data.total_scans} + {data.total_reports} + {new Date(data.createdAt).toLocaleString()} + {new Date(data.updatedAt).toLocaleString()} + + {data.subscription ? ( + <> + + {data.subscription.status} + + {data.subscription.cancelAtPeriodEnd && Cancels at period end} +
+ Renews {new Date(data.subscription.currentPeriodEnd).toLocaleDateString()} +
+ + ) : ( + None + )} +
+ {data.ownedOrg && ( + + {data.ownedOrg.name} + + )} + {data.orgMember && ( + + {data.orgMember.org.name} + {!data.orgMember.isActive && Suspended} + + )} +
+
+ ); +}; diff --git a/client/src/features/superadmin/components/UserDetailTabs/ReportsTab.tsx b/client/src/features/superadmin/components/UserDetailTabs/ReportsTab.tsx new file mode 100644 index 0000000..2ae9fc5 --- /dev/null +++ b/client/src/features/superadmin/components/UserDetailTabs/ReportsTab.tsx @@ -0,0 +1,73 @@ +import { useState } from "react"; +import { useQuery } from "@tanstack/react-query"; +import { Table, Tag } from "antd"; +import { getUserReports } from "../../api/superadmin.api"; + +type ReportRow = { + id: string; + code: string; + is_shared: boolean; + downloads: number; + createdAt: string; + scan: { id: string; scan_code: string; class: string; patient: { full_name: string } | null }; +}; + +export const ReportsTab = ({ userId }: { userId: string }) => { + const [page, setPage] = useState(1); + const pageSize = 10; + const { data, isLoading } = useQuery({ + queryKey: ["superadmin", "user", userId, "reports", page], + queryFn: () => getUserReports(userId, page, pageSize), + }); + + return ( + + dataSource={data?.items ?? []} + rowKey="id" + loading={isLoading} + size="small" + pagination={{ + current: page, + pageSize, + total: data?.total ?? 0, + onChange: setPage, + showSizeChanger: false, + }} + columns={[ + { + title: "Code", + dataIndex: "code", + render: (v: string) => {v}, + }, + { + title: "Scan", + dataIndex: ["scan", "scan_code"], + render: (_: unknown, r: ReportRow) => ( + {r.scan.scan_code} + ), + }, + { + title: "Class", + dataIndex: ["scan", "class"], + render: (v: string) => {v}, + }, + { + title: "Patient", + dataIndex: ["scan", "patient", "full_name"], + render: (_: unknown, r: ReportRow) => r.scan.patient?.full_name ?? "—", + }, + { + title: "Shared", + dataIndex: "is_shared", + render: (v: boolean) => (v ? Shared : "—"), + }, + { title: "Downloads", dataIndex: "downloads" }, + { + title: "Created", + dataIndex: "createdAt", + render: (v: string) => new Date(v).toLocaleString(), + }, + ]} + /> + ); +}; diff --git a/client/src/features/superadmin/components/UserDetailTabs/ScansTab.tsx b/client/src/features/superadmin/components/UserDetailTabs/ScansTab.tsx new file mode 100644 index 0000000..19ff95e --- /dev/null +++ b/client/src/features/superadmin/components/UserDetailTabs/ScansTab.tsx @@ -0,0 +1,82 @@ +import { useState } from "react"; +import { useQuery } from "@tanstack/react-query"; +import { Table, Tag } from "antd"; +import { getUserScans } from "../../api/superadmin.api"; + +type ScanRow = { + id: string; + scan_code: string; + class: string; + confidence_score: number; + status: string; + createdAt: string; + patient: { id: string; full_name: string } | null; + scanImage: { url: string } | null; + report: { id: string; code: string } | null; +}; + +export const ScansTab = ({ userId }: { userId: string }) => { + const [page, setPage] = useState(1); + const pageSize = 10; + + const { data, isLoading } = useQuery({ + queryKey: ["superadmin", "user", userId, "scans", page], + queryFn: () => getUserScans(userId, page, pageSize), + }); + + return ( + + dataSource={data?.items ?? []} + rowKey="id" + loading={isLoading} + size="small" + pagination={{ + current: page, + pageSize, + total: data?.total ?? 0, + onChange: setPage, + showSizeChanger: false, + }} + columns={[ + { + title: "Code", + dataIndex: "scan_code", + render: (v: string) => {v}, + }, + { + title: "Class", + dataIndex: "class", + render: (v: string) => {v}, + }, + { + title: "Confidence", + dataIndex: "confidence_score", + render: (v: number) => `${(v * 100).toFixed(1)}%`, + }, + { + title: "Patient", + dataIndex: ["patient", "full_name"], + render: (_: unknown, r: ScanRow) => r.patient?.full_name ?? "—", + }, + { + title: "Report", + dataIndex: ["report", "code"], + render: (_: unknown, r: ScanRow) => + r.report ? {r.report.code} : "—", + }, + { + title: "Status", + dataIndex: "status", + render: (v: string) => ( + {v} + ), + }, + { + title: "Created", + dataIndex: "createdAt", + render: (v: string) => new Date(v).toLocaleString(), + }, + ]} + /> + ); +}; diff --git a/client/src/features/superadmin/route.ts b/client/src/features/superadmin/route.ts new file mode 100644 index 0000000..bedd9a2 --- /dev/null +++ b/client/src/features/superadmin/route.ts @@ -0,0 +1,59 @@ +import { createRoute, redirect } from "@tanstack/react-router"; +import { rootRoute } from "../../rootRoute"; +import { useAuthStore } from "../../store/auth.store"; +import { SuperAdminLayout } from "./components/SuperAdminLayout"; +import { OverviewPage } from "./routes"; +import { UsersPage } from "./routes/users"; +import { BillingPage } from "./routes/billing"; +import { AuditLogsPage } from "./routes/audit-logs"; +import { TicketsPage } from "./routes/tickets"; +import { TicketDetailPage } from "./routes/tickets-detail"; + +const requireSuperAdmin = () => { + const { accessToken, user } = useAuthStore.getState(); + if (!accessToken) throw redirect({ to: "/login" }); + if (user?.role !== "SUPER_ADMIN") throw redirect({ to: "/" }); +}; + +export const SuperAdminRoute = createRoute({ + getParentRoute: () => rootRoute, + path: "superadmin", + beforeLoad: requireSuperAdmin, + component: SuperAdminLayout, +}); + +export const SuperAdminOverviewRoute = createRoute({ + getParentRoute: () => SuperAdminRoute, + path: "/", + component: OverviewPage, +}); + +export const SuperAdminUsersRoute = createRoute({ + getParentRoute: () => SuperAdminRoute, + path: "users", + component: UsersPage, +}); + +export const SuperAdminBillingRoute = createRoute({ + getParentRoute: () => SuperAdminRoute, + path: "billing", + component: BillingPage, +}); + +export const SuperAdminAuditLogsRoute = createRoute({ + getParentRoute: () => SuperAdminRoute, + path: "audit-logs", + component: AuditLogsPage, +}); + +export const SuperAdminTicketsRoute = createRoute({ + getParentRoute: () => SuperAdminRoute, + path: "tickets", + component: TicketsPage, +}); + +export const SuperAdminTicketDetailRoute = createRoute({ + getParentRoute: () => SuperAdminRoute, + path: "tickets/$code", + component: TicketDetailPage, +}); diff --git a/client/src/features/superadmin/routes/audit-logs.tsx b/client/src/features/superadmin/routes/audit-logs.tsx new file mode 100644 index 0000000..ecee3a6 --- /dev/null +++ b/client/src/features/superadmin/routes/audit-logs.tsx @@ -0,0 +1,192 @@ +import { useState } from "react"; +import { useQuery } from "@tanstack/react-query"; +import { Card, Table, Tag, Input, Select, DatePicker, Button, Space, Drawer, Descriptions } from "antd"; +import { MdSearch, MdFileDownload } from "react-icons/md"; +import dayjs from "dayjs"; +import { listAuditLogs, exportAuditLogs } from "../api/superadmin.api"; +import type { AuditLogItem } from "../api/superadmin.api"; + +const { RangePicker } = DatePicker; + +const severityColor = (s: string) => + s === "success" ? "green" : s === "warning" ? "orange" : s === "danger" ? "red" : "default"; + +export const AuditLogsPage = () => { + const [filters, setFilters] = useState<{ + page: number; + pageSize: number; + search?: string; + category?: string; + status?: string; + from?: string; + to?: string; + }>({ page: 1, pageSize: 30 }); + const [selected, setSelected] = useState(null); + + const { data, isLoading } = useQuery({ + queryKey: ["superadmin", "audit", filters], + queryFn: () => listAuditLogs(filters), + }); + + const onRange = (range: unknown) => { + const r = range as [dayjs.Dayjs | null, dayjs.Dayjs | null] | null; + setFilters((f) => ({ + ...f, + from: r?.[0]?.toISOString(), + to: r?.[1]?.toISOString(), + page: 1, + })); + }; + + return ( + + } + placeholder="Search action, actor, target…" + allowClear + onChange={(e) => setFilters((f) => ({ ...f, search: e.target.value || undefined, page: 1 }))} + style={{ width: 250 }} + /> + setFilters((f) => ({ ...f, status: v, page: 1 }))} + options={[ + { value: "success", label: "Success" }, + { value: "failed", label: "Failed" }, + ]} + style={{ width: 120 }} + /> + + + + } + > + + dataSource={data?.items ?? []} + rowKey="id" + loading={isLoading} + size="small" + onRow={(record) => ({ + onClick: () => setSelected(record), + style: { cursor: "pointer" }, + })} + pagination={{ + current: filters.page, + pageSize: filters.pageSize, + total: data?.total ?? 0, + onChange: (page, pageSize) => setFilters((f) => ({ ...f, page, pageSize })), + showSizeChanger: true, + }} + columns={[ + { + title: "When", + dataIndex: "createdAt", + width: 170, + render: (v: string) => new Date(v).toLocaleString(), + }, + { + title: "Actor", + render: (_: unknown, r: AuditLogItem) => ( +
+
{r.actorName}
+
{r.actorEmail}
+
+ ), + }, + { title: "Action", dataIndex: "action" }, + { + title: "Category", + dataIndex: "category", + render: (v: string) => {v}, + }, + { title: "Target", dataIndex: "target", ellipsis: true }, + { + title: "Org", + render: (_: unknown, r: AuditLogItem) => + r.organization ? {r.organization.name} : , + }, + { + title: "Severity", + dataIndex: "severity", + render: (v: string) => {v}, + }, + { + title: "Status", + dataIndex: "status", + render: (v: string) => ( + {v} + ), + }, + ]} + /> + + setSelected(null)} + width={520} + > + {selected && ( + + {selected.id} + + {new Date(selected.createdAt).toLocaleString()} + + + {selected.actorName}
+ {selected.actorEmail} +
+ {selected.action} + {selected.category} + + {selected.severity} + + {selected.status} + + {selected.organization?.name ?? "—"} + + {selected.target} + {selected.targetId ?? "—"} + {selected.ip ?? "—"} + + + {selected.userAgent ?? "—"} + + +
+ )} +
+
+ ); +}; diff --git a/client/src/features/superadmin/routes/billing.tsx b/client/src/features/superadmin/routes/billing.tsx new file mode 100644 index 0000000..69f4554 --- /dev/null +++ b/client/src/features/superadmin/routes/billing.tsx @@ -0,0 +1,265 @@ +import { useState } from "react"; +import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; +import { Card, Table, Tag, Avatar, Space, Select, Input, Button, Collapse, message, Popconfirm } from "antd"; +import { MdAttachMoney, MdSync, MdSearch } from "react-icons/md"; +import { + getBillingKpis, + listSubscriptions, + syncSubscription, + cancelSubscription, + recentPayments, +} from "../api/superadmin.api"; +import type { Subscription, Payment } from "../api/superadmin.api"; +import { KPICard } from "../components/KPICard"; + +const fmtMoney = (cents: number) => + `$${(cents / 100).toLocaleString(undefined, { maximumFractionDigits: 2 })}`; + +export const BillingPage = () => { + const qc = useQueryClient(); + const [filters, setFilters] = useState<{ + page: number; + pageSize: number; + status?: string; + plan?: string; + q?: string; + }>({ page: 1, pageSize: 20 }); + + const kpisQ = useQuery({ queryKey: ["superadmin", "billing", "kpis"], queryFn: getBillingKpis }); + const subsQ = useQuery({ + queryKey: ["superadmin", "billing", "subs", filters], + queryFn: () => listSubscriptions(filters), + }); + const paymentsQ = useQuery({ + queryKey: ["superadmin", "billing", "payments"], + queryFn: () => recentPayments(30), + }); + + const syncMut = useMutation({ + mutationFn: (id: string) => syncSubscription(id), + onSuccess: () => { + message.success("Synced with Stripe"); + qc.invalidateQueries({ queryKey: ["superadmin", "billing"] }); + }, + onError: (e: unknown) => + message.error((e as { response?: { data?: { message?: string } } }).response?.data?.message ?? "Sync failed"), + }); + const cancelMut = useMutation({ + mutationFn: (id: string) => cancelSubscription(id), + onSuccess: () => { + message.success("Subscription will cancel at period end"); + qc.invalidateQueries({ queryKey: ["superadmin", "billing"] }); + }, + onError: (e: unknown) => + message.error((e as { response?: { data?: { message?: string } } }).response?.data?.message ?? "Cancel failed"), + }); + + const kpis = kpisQ.data; + + return ( +
+
+ } + accent="#16a34a" + /> + + + + +
+ + + } + placeholder="Search user…" + allowClear + onChange={(e) => setFilters((f) => ({ ...f, q: e.target.value || undefined, page: 1 }))} + style={{ width: 220 }} + /> + setFilters((f) => ({ ...f, plan: v, page: 1 }))} + options={[ + { value: "DOCTOR", label: "Doctor" }, + { value: "ORGANIZATION", label: "Organization" }, + ]} + style={{ width: 140 }} + /> + + } + > + + dataSource={subsQ.data?.items ?? []} + rowKey="id" + loading={subsQ.isLoading} + size="middle" + pagination={{ + current: filters.page, + pageSize: filters.pageSize, + total: subsQ.data?.total ?? 0, + onChange: (page, pageSize) => setFilters((f) => ({ ...f, page, pageSize })), + }} + columns={[ + { + title: "User", + render: (_: unknown, r: Subscription) => ( +
+ + {r.user.username.slice(0, 2).toUpperCase()} + +
+
{r.user.username}
+
{r.user.email}
+
+
+ ), + }, + { + title: "Plan", + dataIndex: ["user", "plan"], + render: (v: string) => ( + {v} + ), + }, + { + title: "Status", + dataIndex: "status", + render: (v: string, r: Subscription) => ( + <> + {v} + {r.cancelAtPeriodEnd && Ends at period} + + ), + }, + { + title: "Stripe ID", + dataIndex: "stripeSubscriptionId", + render: (v: string) => ( + {v.slice(0, 18)}… + ), + }, + { + title: "Renews", + dataIndex: "currentPeriodEnd", + render: (v: string) => new Date(v).toLocaleDateString(), + }, + { + title: "Actions", + render: (_: unknown, r: Subscription) => ( + + + cancelMut.mutate(r.stripeSubscriptionId)} + disabled={r.cancelAtPeriodEnd || r.status !== "active"} + > + + + + ), + }, + ]} + /> +
+ + + dataSource={paymentsQ.data ?? []} + rowKey="id" + loading={paymentsQ.isLoading} + size="small" + pagination={{ pageSize: 10 }} + columns={[ + { + title: "When", + dataIndex: "createdAt", + render: (v: string) => new Date(v).toLocaleString(), + }, + { + title: "User", + render: (_: unknown, r: Payment) => ( + + {r.user.username}{" "} + · {r.user.email} + + ), + }, + { + title: "Plan", + dataIndex: "plan", + render: (v: string) => {v}, + }, + { + title: "Mode", + dataIndex: "mode", + render: (v: string) => {v}, + }, + { + title: "Amount", + dataIndex: "amount", + render: (v: number) => fmtMoney(v), + }, + { + title: "Status", + dataIndex: "status", + render: (v: string) => ( + {v} + ), + }, + { + title: "Invoice", + dataIndex: "stripePaymentId", + render: (v: string) => ( + {v} + ), + }, + ]} + /> + ), + }, + ]} + /> +
+ ); +}; diff --git a/client/src/features/superadmin/routes/index.tsx b/client/src/features/superadmin/routes/index.tsx new file mode 100644 index 0000000..ef58996 --- /dev/null +++ b/client/src/features/superadmin/routes/index.tsx @@ -0,0 +1,513 @@ +import { useState } from "react"; +import { useQuery } from "@tanstack/react-query"; +import { Link } from "@tanstack/react-router"; +import { Card, Skeleton, Tag, Avatar } from "antd"; +import { + MdPeopleAlt, + MdAttachMoney, + MdImage, + MdDescription, + MdSupportAgent, + MdTrendingUp, + MdTrendingDown, +} from "react-icons/md"; +import { getOverview } from "../api/superadmin.api"; +import { KPICard } from "../components/KPICard"; +import { AreaChart } from "../components/AreaChart"; + +const fmtMoney = (cents: number) => + `$${(cents / 100).toLocaleString(undefined, { maximumFractionDigits: 0 })}`; + +const PlanPie = ({ free, doctor, org }: { free: number; doctor: number; org: number }) => { + const total = free + doctor + org; + const safeTotal = total || 1; + const slices = [ + { key: "free", label: "Free", value: free, color: "#94a3b8" }, + { key: "doctor", label: "Doctor", value: doctor, color: "#2563eb" }, + { key: "org", label: "Organization", value: org, color: "#10b981" }, + ]; + + const [hovered, setHovered] = useState(null); + + // Donut geometry + const size = 160; + const cx = size / 2; + const cy = size / 2; + const rOuter = 70; + const rInner = 48; + const TAU = Math.PI * 2; + const startAngle = -Math.PI / 2; // 12 o'clock + + let cum = 0; + const segments = slices.map((s) => { + const startFrac = cum; + cum += s.value / safeTotal; + const endFrac = cum; + const a0 = startAngle + startFrac * TAU; + const a1 = startAngle + endFrac * TAU; + const large = a1 - a0 > Math.PI ? 1 : 0; + + // Outer arc + const x0o = cx + rOuter * Math.cos(a0); + const y0o = cy + rOuter * Math.sin(a0); + const x1o = cx + rOuter * Math.cos(a1); + const y1o = cy + rOuter * Math.sin(a1); + // Inner arc + const x0i = cx + rInner * Math.cos(a0); + const y0i = cy + rInner * Math.sin(a0); + const x1i = cx + rInner * Math.cos(a1); + const y1i = cy + rInner * Math.sin(a1); + + const d = + s.value === 0 + ? "" + : `M${x0o},${y0o} A${rOuter},${rOuter} 0 ${large} 1 ${x1o},${y1o} ` + + `L${x1i},${y1i} A${rInner},${rInner} 0 ${large} 0 ${x0i},${y0i} Z`; + + const pct = total === 0 ? 0 : (s.value / total) * 100; + return { ...s, d, pct, startFrac }; + }); + + const paid = doctor + org; + const paidPct = total === 0 ? 0 : (paid / total) * 100; + const focus = hovered ? segments.find((s) => s.key === hovered) : null; + + return ( +
+
+ + {/* Empty-state ring */} + {total === 0 && ( + + )} + {segments.map((s) => { + if (!s.d) return null; + const active = hovered === null || hovered === s.key; + return ( + setHovered(s.key)} + onMouseLeave={() => setHovered(null)} + /> + ); + })} + + {/* Center label */} +
+
+ {focus ? focus.label : "Total"} +
+
+ {focus ? focus.value.toLocaleString() : total.toLocaleString()} +
+
+ {focus ? `${focus.pct.toFixed(1)}%` : `${paidPct.toFixed(0)}% paid`} +
+
+
+ + {/* Legend */} +
+ {segments.map((s) => { + const active = hovered === null || hovered === s.key; + return ( +
setHovered(s.key)} + onMouseLeave={() => setHovered(null)} + style={{ + display: "flex", + alignItems: "center", + gap: 10, + padding: "6px 8px", + borderRadius: 8, + background: hovered === s.key ? `${s.color}14` : "transparent", + opacity: active ? 1 : 0.5, + transition: "background 150ms ease, opacity 150ms ease", + cursor: "pointer", + }} + > + +
+
+ {s.label} + + {s.value.toLocaleString()} + +
+
+
+
+
+ {s.pct.toFixed(1)}% of total +
+
+
+ ); + })} +
+
+ ); +}; + +export const OverviewPage = () => { + const { data, isLoading } = useQuery({ + queryKey: ["superadmin", "overview"], + queryFn: getOverview, + }); + + if (isLoading || !data) { + return ( +
+ + +
+ ); + } + + const delta = data.usersDelta7d; + const positive = delta >= 0; + + return ( +
+
+ } + sub={ + + {positive ? : } + {Math.abs(delta)}% vs prev. 7d + + } + /> + } + accent="#10b981" + /> + } + accent="#16a34a" + /> + } + accent="#7c3aed" + /> + } + accent="#f59e0b" + /> +
+ +
+ Last 30 days} + styles={{ body: { padding: 18 } }} + > + + + Last 30 days} + styles={{ body: { padding: 18 } }} + > + + +
+ + All users} + styles={{ body: { padding: 20 } }} + > + + + +
+ {data.recentSignups.length} latest} + styles={{ body: { padding: 0 } }} + > + {data.recentSignups.length === 0 ? ( +
No signups yet
+ ) : ( +
+ {data.recentSignups.map((u, i) => ( +
(e.currentTarget.style.background = "#f8fafc")} + onMouseLeave={(e) => (e.currentTarget.style.background = "transparent")} + > + + {u.username?.slice(0, 2).toUpperCase()} + +
+
+ {u.username} +
+
+ {u.email} +
+
+
+ + {u.plan} + + + {timeAgo(u.createdAt)} + +
+
+ ))} +
+ )} +
+ + + Open tickets + {data.openTicketsCount} +
+ } + extra={ + + View all + + } + styles={{ body: { padding: 0 } }} + > + {data.recentTickets.length === 0 ? ( +
No tickets yet
+ ) : ( +
+ {data.recentTickets.map((t, i) => ( + (e.currentTarget.style.background = "#f8fafc")} + onMouseLeave={(e) => (e.currentTarget.style.background = "transparent")} + > +
+ + {t.code} + + + {t.type} + + + {t.status} + + + {t.priority} + + + {timeAgo(t.createdAt)} + +
+
+ {t.reason} — by {t.submittedBy.username} +
+ + ))} +
+ )} + +
+
+ ); +}; + +function timeAgo(iso: string): string { + const diff = Date.now() - new Date(iso).getTime(); + const sec = Math.floor(diff / 1000); + if (sec < 60) return `${sec}s ago`; + const min = Math.floor(sec / 60); + if (min < 60) return `${min}m ago`; + const hr = Math.floor(min / 60); + if (hr < 24) return `${hr}h ago`; + const day = Math.floor(hr / 24); + if (day < 7) return `${day}d ago`; + const wk = Math.floor(day / 7); + if (wk < 5) return `${wk}w ago`; + const mo = Math.floor(day / 30); + if (mo < 12) return `${mo}mo ago`; + return `${Math.floor(day / 365)}y ago`; +} diff --git a/client/src/features/superadmin/routes/tickets-detail.tsx b/client/src/features/superadmin/routes/tickets-detail.tsx new file mode 100644 index 0000000..0a61c93 --- /dev/null +++ b/client/src/features/superadmin/routes/tickets-detail.tsx @@ -0,0 +1,297 @@ +import { useState } from "react"; +import { useParams } from "@tanstack/react-router"; +import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; +import { + Card, + Skeleton, + Tag, + Avatar, + Descriptions, + Button, + Input, + Space, + Modal, + message, + Image, + Empty, +} from "antd"; +import { + MdReplay, + MdAutorenew, + MdCheckCircle, + MdCancel, +} from "react-icons/md"; +import { + getTicket, + reanalyzeTicket, + regenerateTicket, + resolveTicket, + dismissTicket, +} from "../api/superadmin.api"; + +const statusColor = (s: string) => + s === "OPEN" ? "red" : s === "IN_PROGRESS" ? "orange" : s === "RESOLVED" ? "green" : "default"; + +export const TicketDetailPage = () => { + const { code } = useParams({ from: "/superadmin/tickets/$code" }); + const qc = useQueryClient(); + const [resolutionNote, setResolutionNote] = useState(""); + + const { data, isLoading } = useQuery({ + queryKey: ["superadmin", "ticket", code], + queryFn: () => getTicket(code), + }); + + const invalidate = () => qc.invalidateQueries({ queryKey: ["superadmin", "ticket", code] }); + + const reanalyzeMut = useMutation({ + mutationFn: () => reanalyzeTicket(code), + onSuccess: () => { + message.success("Re-analysis completed"); + invalidate(); + }, + onError: (e: unknown) => + message.error((e as { response?: { data?: { message?: string } } }).response?.data?.message ?? "Failed"), + }); + const regenerateMut = useMutation({ + mutationFn: () => regenerateTicket(code), + onSuccess: () => { + message.success("Report regeneration queued"); + invalidate(); + }, + onError: (e: unknown) => + message.error((e as { response?: { data?: { message?: string } } }).response?.data?.message ?? "Failed"), + }); + const resolveMut = useMutation({ + mutationFn: () => resolveTicket(code, resolutionNote), + onSuccess: () => { + message.success("Ticket resolved"); + invalidate(); + }, + onError: (e: unknown) => + message.error((e as { response?: { data?: { message?: string } } }).response?.data?.message ?? "Failed"), + }); + const dismissMut = useMutation({ + mutationFn: () => dismissTicket(code, resolutionNote || undefined), + onSuccess: () => { + message.success("Ticket dismissed"); + invalidate(); + }, + onError: (e: unknown) => + message.error((e as { response?: { data?: { message?: string } } }).response?.data?.message ?? "Failed"), + }); + + if (isLoading || !data) return ; + + const isReAnalysis = data.type === "RE_ANALYSIS"; + const closed = data.status === "RESOLVED" || data.status === "DISMISSED"; + + return ( +
+ {/* Panel 1: Info + timeline */} + + {data.code}{" "} + {data.type}{" "} + {data.status} + + } + styles={{ body: { padding: 14 } }} + > + + +
+ + {data.submittedBy.username.slice(0, 2).toUpperCase()} + +
+
{data.submittedBy.username}
+
+ {data.submittedBy.email} · {data.submittedBy.plan} +
+
+
+
+ + + {data.priority} + + + + {new Date(data.createdAt).toLocaleString()} + + + {new Date(data.updatedAt).toLocaleString()} + + {data.resolvedAt && ( + + {new Date(data.resolvedAt).toLocaleString()} + + )} + {data.assignedTo && ( + + {data.assignedTo.username} + + )} + +
{data.reason}
+
+ {data.resolutionNote && ( + +
{data.resolutionNote}
+
+ )} +
+
+ + {/* Panel 2: Artifact */} + + {isReAnalysis && data.scan ? ( +
+ + + {data.scan.scan_code} + + + {data.scan.class} + + {data.scan.patient && ( + {data.scan.patient.full_name} + )} + + {data.scan.scanImage && ( + + )} + {data.reanalysisScan && ( + +
+ {data.reanalysisScan.scan_code} +
+
+ Class: {data.reanalysisScan.class} Confidence:{" "} + {(data.reanalysisScan.confidence_score * 100).toFixed(1)}% +
+
+ )} +
+ ) : !isReAnalysis && data.report ? ( +
+ + + {data.report.code} + + + {data.report.scan.scan_code} + + {data.report.scan.patient && ( + + {data.report.scan.patient.full_name} + + )} + + +
+                                {JSON.stringify(data.report.content, null, 2)}
+                            
+
+ {data.reanalysisReport && ( + + {data.reanalysisReport.code} + + )} +
+ ) : ( + + )} +
+ + {/* Panel 3: Actions */} + + + {isReAnalysis && ( + + )} + {!isReAnalysis && ( + + )} + +
+ + setResolutionNote(e.target.value)} + disabled={closed} + /> + + + + +
+ ); +}; diff --git a/client/src/features/superadmin/routes/tickets.tsx b/client/src/features/superadmin/routes/tickets.tsx new file mode 100644 index 0000000..ef1ead9 --- /dev/null +++ b/client/src/features/superadmin/routes/tickets.tsx @@ -0,0 +1,153 @@ +import { useState } from "react"; +import { useQuery } from "@tanstack/react-query"; +import { useNavigate } from "@tanstack/react-router"; +import { Card, Table, Tag, Select, Input, Space, Avatar } from "antd"; +import { MdSearch } from "react-icons/md"; +import { listTickets } from "../api/superadmin.api"; +import type { TicketListItem } from "../api/superadmin.api"; + +const statusColor = (s: TicketListItem["status"]) => + s === "OPEN" ? "red" : s === "IN_PROGRESS" ? "orange" : s === "RESOLVED" ? "green" : "default"; +const priorityColor = (p: TicketListItem["priority"]) => + p === "HIGH" ? "red" : p === "MEDIUM" ? "orange" : "blue"; + +export const TicketsPage = () => { + const navigate = useNavigate(); + const [filters, setFilters] = useState<{ + page: number; + pageSize: number; + status?: string; + type?: string; + priority?: string; + q?: string; + }>({ page: 1, pageSize: 20, status: "OPEN" }); + + const { data, isLoading } = useQuery({ + queryKey: ["superadmin", "tickets", filters], + queryFn: () => listTickets(filters), + }); + + return ( + + } + placeholder="Code, reason, submitter…" + allowClear + onChange={(e) => setFilters((f) => ({ ...f, q: e.target.value || undefined, page: 1 }))} + style={{ width: 240 }} + /> + setFilters((f) => ({ ...f, type: v, page: 1 }))} + options={[ + { value: "RE_ANALYSIS", label: "Re-analysis" }, + { value: "RE_REPORT", label: "Re-report" }, + ]} + style={{ width: 140 }} + /> + } + placeholder="Search email or name…" + allowClear + onChange={(e) => update({ q: e.target.value || undefined })} + style={{ width: 240 }} + /> + update({ role: v })} + options={[ + { value: "USER", label: "User" }, + { value: "ADMIN", label: "Admin" }, + { value: "SUPER_ADMIN", label: "Super Admin" }, + ]} + style={{ width: 140 }} + /> + update({ hasOrg: v })} + options={[ + { value: "true", label: "Yes" }, + { value: "false", label: "No" }, + ]} + style={{ width: 110 }} + /> +
+ } + > + + dataSource={data?.items ?? []} + rowKey="id" + loading={isLoading} + size="middle" + onRow={(record) => ({ + onClick: () => setSelectedId(record.id), + style: { cursor: "pointer" }, + })} + pagination={{ + current: filters.page, + pageSize: filters.pageSize, + total: data?.total ?? 0, + onChange: (page, pageSize) => setFilters((f) => ({ ...f, page, pageSize })), + showSizeChanger: true, + }} + columns={[ + { + title: "User", + render: (_: unknown, r: UserListItem) => ( +
+ + {r.username.slice(0, 2).toUpperCase()} + +
+
+ {r.username} +
+
{r.email}
+
+
+ ), + }, + { + title: "Plan", + dataIndex: "plan", + render: (v: string) => ( + + {v} + + ), + }, + { + title: "Role", + dataIndex: "role", + render: (v: string) => ( + {v} + ), + }, + { + title: "Org", + render: (_: unknown, r: UserListItem) => + r.ownedOrg ? {r.ownedOrg.name} : r.orgMember ? Member : "—", + }, + { title: "Scans", dataIndex: "total_scans", width: 80 }, + { title: "Reports", dataIndex: "total_reports", width: 90 }, + { + title: "Status", + dataIndex: "is_active", + render: (v: boolean) => ( + {v ? "Active" : "Inactive"} + ), + }, + { + title: "Joined", + dataIndex: "createdAt", + render: (v: string) => new Date(v).toLocaleDateString(), + }, + ]} + /> + + setSelectedId(null)} + /> +
+ ); +}; diff --git a/client/src/router.ts b/client/src/router.ts index 3b37c65..1acd4d9 100644 --- a/client/src/router.ts +++ b/client/src/router.ts @@ -25,6 +25,15 @@ import { // OrganizationWebHooksRoute, OrganizationAuditLogsRoute, } from "./features/dashboard/Organization/routes"; +import { + SuperAdminRoute, + SuperAdminOverviewRoute, + SuperAdminUsersRoute, + SuperAdminBillingRoute, + SuperAdminAuditLogsRoute, + SuperAdminTicketsRoute, + SuperAdminTicketDetailRoute, +} from "./features/superadmin/route"; const routeTree = rootRoute.addChildren([ AppLayoutRoute.addChildren([ @@ -54,6 +63,14 @@ const routeTree = rootRoute.addChildren([ ForgotPasswordPageRoute, ResetPasswordPageRoute, GoogleCallbackRoute, + SuperAdminRoute.addChildren([ + SuperAdminOverviewRoute, + SuperAdminUsersRoute, + SuperAdminBillingRoute, + SuperAdminAuditLogsRoute, + SuperAdminTicketsRoute, + SuperAdminTicketDetailRoute, + ]), ]) export const router = createRouter({routeTree}); diff --git a/server/prisma/generated/client/browser.ts b/server/prisma/generated/client/browser.ts index 5aee504..bcdf850 100644 --- a/server/prisma/generated/client/browser.ts +++ b/server/prisma/generated/client/browser.ts @@ -87,6 +87,11 @@ export type Subscription = Prisma.SubscriptionModel * */ export type Payment = Prisma.PaymentModel +/** + * Model Ticket + * + */ +export type Ticket = Prisma.TicketModel /** * Model AuditLog * diff --git a/server/prisma/generated/client/client.ts b/server/prisma/generated/client/client.ts index aada271..8785627 100644 --- a/server/prisma/generated/client/client.ts +++ b/server/prisma/generated/client/client.ts @@ -109,6 +109,11 @@ export type Subscription = Prisma.SubscriptionModel * */ export type Payment = Prisma.PaymentModel +/** + * Model Ticket + * + */ +export type Ticket = Prisma.TicketModel /** * Model AuditLog * diff --git a/server/prisma/generated/client/commonInputTypes.ts b/server/prisma/generated/client/commonInputTypes.ts index 10e4eba..d3fe6fa 100644 --- a/server/prisma/generated/client/commonInputTypes.ts +++ b/server/prisma/generated/client/commonInputTypes.ts @@ -406,6 +406,57 @@ export type EnumPaymentModeWithAggregatesFilter<$PrismaModel = never> = { _max?: Prisma.NestedEnumPaymentModeFilter<$PrismaModel> } +export type EnumTicketTypeFilter<$PrismaModel = never> = { + equals?: $Enums.TicketType | Prisma.EnumTicketTypeFieldRefInput<$PrismaModel> + in?: $Enums.TicketType[] | Prisma.ListEnumTicketTypeFieldRefInput<$PrismaModel> + notIn?: $Enums.TicketType[] | Prisma.ListEnumTicketTypeFieldRefInput<$PrismaModel> + not?: Prisma.NestedEnumTicketTypeFilter<$PrismaModel> | $Enums.TicketType +} + +export type EnumTicketStatusFilter<$PrismaModel = never> = { + equals?: $Enums.TicketStatus | Prisma.EnumTicketStatusFieldRefInput<$PrismaModel> + in?: $Enums.TicketStatus[] | Prisma.ListEnumTicketStatusFieldRefInput<$PrismaModel> + notIn?: $Enums.TicketStatus[] | Prisma.ListEnumTicketStatusFieldRefInput<$PrismaModel> + not?: Prisma.NestedEnumTicketStatusFilter<$PrismaModel> | $Enums.TicketStatus +} + +export type EnumTicketPriorityFilter<$PrismaModel = never> = { + equals?: $Enums.TicketPriority | Prisma.EnumTicketPriorityFieldRefInput<$PrismaModel> + in?: $Enums.TicketPriority[] | Prisma.ListEnumTicketPriorityFieldRefInput<$PrismaModel> + notIn?: $Enums.TicketPriority[] | Prisma.ListEnumTicketPriorityFieldRefInput<$PrismaModel> + not?: Prisma.NestedEnumTicketPriorityFilter<$PrismaModel> | $Enums.TicketPriority +} + +export type EnumTicketTypeWithAggregatesFilter<$PrismaModel = never> = { + equals?: $Enums.TicketType | Prisma.EnumTicketTypeFieldRefInput<$PrismaModel> + in?: $Enums.TicketType[] | Prisma.ListEnumTicketTypeFieldRefInput<$PrismaModel> + notIn?: $Enums.TicketType[] | Prisma.ListEnumTicketTypeFieldRefInput<$PrismaModel> + not?: Prisma.NestedEnumTicketTypeWithAggregatesFilter<$PrismaModel> | $Enums.TicketType + _count?: Prisma.NestedIntFilter<$PrismaModel> + _min?: Prisma.NestedEnumTicketTypeFilter<$PrismaModel> + _max?: Prisma.NestedEnumTicketTypeFilter<$PrismaModel> +} + +export type EnumTicketStatusWithAggregatesFilter<$PrismaModel = never> = { + equals?: $Enums.TicketStatus | Prisma.EnumTicketStatusFieldRefInput<$PrismaModel> + in?: $Enums.TicketStatus[] | Prisma.ListEnumTicketStatusFieldRefInput<$PrismaModel> + notIn?: $Enums.TicketStatus[] | Prisma.ListEnumTicketStatusFieldRefInput<$PrismaModel> + not?: Prisma.NestedEnumTicketStatusWithAggregatesFilter<$PrismaModel> | $Enums.TicketStatus + _count?: Prisma.NestedIntFilter<$PrismaModel> + _min?: Prisma.NestedEnumTicketStatusFilter<$PrismaModel> + _max?: Prisma.NestedEnumTicketStatusFilter<$PrismaModel> +} + +export type EnumTicketPriorityWithAggregatesFilter<$PrismaModel = never> = { + equals?: $Enums.TicketPriority | Prisma.EnumTicketPriorityFieldRefInput<$PrismaModel> + in?: $Enums.TicketPriority[] | Prisma.ListEnumTicketPriorityFieldRefInput<$PrismaModel> + notIn?: $Enums.TicketPriority[] | Prisma.ListEnumTicketPriorityFieldRefInput<$PrismaModel> + not?: Prisma.NestedEnumTicketPriorityWithAggregatesFilter<$PrismaModel> | $Enums.TicketPriority + _count?: Prisma.NestedIntFilter<$PrismaModel> + _min?: Prisma.NestedEnumTicketPriorityFilter<$PrismaModel> + _max?: Prisma.NestedEnumTicketPriorityFilter<$PrismaModel> +} + export type EnumAuditCategoryFilter<$PrismaModel = never> = { equals?: $Enums.AuditCategory | Prisma.EnumAuditCategoryFieldRefInput<$PrismaModel> in?: $Enums.AuditCategory[] | Prisma.ListEnumAuditCategoryFieldRefInput<$PrismaModel> @@ -824,6 +875,57 @@ export type NestedEnumPaymentModeWithAggregatesFilter<$PrismaModel = never> = { _max?: Prisma.NestedEnumPaymentModeFilter<$PrismaModel> } +export type NestedEnumTicketTypeFilter<$PrismaModel = never> = { + equals?: $Enums.TicketType | Prisma.EnumTicketTypeFieldRefInput<$PrismaModel> + in?: $Enums.TicketType[] | Prisma.ListEnumTicketTypeFieldRefInput<$PrismaModel> + notIn?: $Enums.TicketType[] | Prisma.ListEnumTicketTypeFieldRefInput<$PrismaModel> + not?: Prisma.NestedEnumTicketTypeFilter<$PrismaModel> | $Enums.TicketType +} + +export type NestedEnumTicketStatusFilter<$PrismaModel = never> = { + equals?: $Enums.TicketStatus | Prisma.EnumTicketStatusFieldRefInput<$PrismaModel> + in?: $Enums.TicketStatus[] | Prisma.ListEnumTicketStatusFieldRefInput<$PrismaModel> + notIn?: $Enums.TicketStatus[] | Prisma.ListEnumTicketStatusFieldRefInput<$PrismaModel> + not?: Prisma.NestedEnumTicketStatusFilter<$PrismaModel> | $Enums.TicketStatus +} + +export type NestedEnumTicketPriorityFilter<$PrismaModel = never> = { + equals?: $Enums.TicketPriority | Prisma.EnumTicketPriorityFieldRefInput<$PrismaModel> + in?: $Enums.TicketPriority[] | Prisma.ListEnumTicketPriorityFieldRefInput<$PrismaModel> + notIn?: $Enums.TicketPriority[] | Prisma.ListEnumTicketPriorityFieldRefInput<$PrismaModel> + not?: Prisma.NestedEnumTicketPriorityFilter<$PrismaModel> | $Enums.TicketPriority +} + +export type NestedEnumTicketTypeWithAggregatesFilter<$PrismaModel = never> = { + equals?: $Enums.TicketType | Prisma.EnumTicketTypeFieldRefInput<$PrismaModel> + in?: $Enums.TicketType[] | Prisma.ListEnumTicketTypeFieldRefInput<$PrismaModel> + notIn?: $Enums.TicketType[] | Prisma.ListEnumTicketTypeFieldRefInput<$PrismaModel> + not?: Prisma.NestedEnumTicketTypeWithAggregatesFilter<$PrismaModel> | $Enums.TicketType + _count?: Prisma.NestedIntFilter<$PrismaModel> + _min?: Prisma.NestedEnumTicketTypeFilter<$PrismaModel> + _max?: Prisma.NestedEnumTicketTypeFilter<$PrismaModel> +} + +export type NestedEnumTicketStatusWithAggregatesFilter<$PrismaModel = never> = { + equals?: $Enums.TicketStatus | Prisma.EnumTicketStatusFieldRefInput<$PrismaModel> + in?: $Enums.TicketStatus[] | Prisma.ListEnumTicketStatusFieldRefInput<$PrismaModel> + notIn?: $Enums.TicketStatus[] | Prisma.ListEnumTicketStatusFieldRefInput<$PrismaModel> + not?: Prisma.NestedEnumTicketStatusWithAggregatesFilter<$PrismaModel> | $Enums.TicketStatus + _count?: Prisma.NestedIntFilter<$PrismaModel> + _min?: Prisma.NestedEnumTicketStatusFilter<$PrismaModel> + _max?: Prisma.NestedEnumTicketStatusFilter<$PrismaModel> +} + +export type NestedEnumTicketPriorityWithAggregatesFilter<$PrismaModel = never> = { + equals?: $Enums.TicketPriority | Prisma.EnumTicketPriorityFieldRefInput<$PrismaModel> + in?: $Enums.TicketPriority[] | Prisma.ListEnumTicketPriorityFieldRefInput<$PrismaModel> + notIn?: $Enums.TicketPriority[] | Prisma.ListEnumTicketPriorityFieldRefInput<$PrismaModel> + not?: Prisma.NestedEnumTicketPriorityWithAggregatesFilter<$PrismaModel> | $Enums.TicketPriority + _count?: Prisma.NestedIntFilter<$PrismaModel> + _min?: Prisma.NestedEnumTicketPriorityFilter<$PrismaModel> + _max?: Prisma.NestedEnumTicketPriorityFilter<$PrismaModel> +} + export type NestedEnumAuditCategoryFilter<$PrismaModel = never> = { equals?: $Enums.AuditCategory | Prisma.EnumAuditCategoryFieldRefInput<$PrismaModel> in?: $Enums.AuditCategory[] | Prisma.ListEnumAuditCategoryFieldRefInput<$PrismaModel> diff --git a/server/prisma/generated/client/enums.ts b/server/prisma/generated/client/enums.ts index 7772255..d336cd5 100644 --- a/server/prisma/generated/client/enums.ts +++ b/server/prisma/generated/client/enums.ts @@ -11,7 +11,7 @@ export const Role = { USER: 'USER', - ADMIN: 'ADMIN' + SUPER_ADMIN: 'SUPER_ADMIN' } as const export type Role = (typeof Role)[keyof typeof Role] @@ -90,6 +90,33 @@ export const PaymentMode = { export type PaymentMode = (typeof PaymentMode)[keyof typeof PaymentMode] +export const TicketType = { + RE_ANALYSIS: 'RE_ANALYSIS', + RE_REPORT: 'RE_REPORT' +} as const + +export type TicketType = (typeof TicketType)[keyof typeof TicketType] + + +export const TicketStatus = { + OPEN: 'OPEN', + IN_PROGRESS: 'IN_PROGRESS', + RESOLVED: 'RESOLVED', + DISMISSED: 'DISMISSED' +} as const + +export type TicketStatus = (typeof TicketStatus)[keyof typeof TicketStatus] + + +export const TicketPriority = { + LOW: 'LOW', + MEDIUM: 'MEDIUM', + HIGH: 'HIGH' +} as const + +export type TicketPriority = (typeof TicketPriority)[keyof typeof TicketPriority] + + export const AuditCategory = { scans: 'scans', patients: 'patients', diff --git a/server/prisma/generated/client/internal/class.ts b/server/prisma/generated/client/internal/class.ts index 87b1947..7de2609 100644 --- a/server/prisma/generated/client/internal/class.ts +++ b/server/prisma/generated/client/internal/class.ts @@ -20,7 +20,7 @@ const config: runtime.GetPrismaClientConfig = { "clientVersion": "7.6.0", "engineVersion": "75cbdc1eb7150937890ad5465d861175c6624711", "activeProvider": "postgresql", - "inlineSchema": "datasource db {\n provider = \"postgresql\"\n}\n\ngenerator client {\n provider = \"prisma-client\"\n output = \"./generated/client\"\n moduleFormat = \"cjs\"\n}\n\n// User\nenum Role {\n USER\n ADMIN\n}\n\nenum Plan {\n FREE\n DOCTOR\n ORGANIZATION\n}\n\nmodel User {\n id String @id @default(uuid())\n username String @unique\n email String @unique\n password String?\n googleId String? @unique\n profile_image_url String?\n plan Plan @default(FREE)\n role Role @default(USER)\n is_active Boolean @default(true)\n\n total_scans Int @default(0)\n total_reports Int @default(0)\n\n twoFactorSecret String?\n twoFactorEnabled Boolean @default(false)\n\n reset_password_token String?\n reset_token_expires DateTime?\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Relations\n patients Patient[]\n scans Scan[]\n notifications Notifications[]\n emailNotification EmailNotification?\n inAppNotification InAppNotification?\n sessions Session[]\n\n ownedOrg Organization? @relation(\"OrgOwner\")\n orgMember OrgMember? @relation(\"OrgMember\")\n\n subscription Subscription?\n payments Payment[]\n\n auditLogs AuditLog[]\n}\n\n// HOSPITAL\nmodel Organization {\n id String @id @default(uuid())\n name String\n ownerId String @unique\n owner User @relation(\"OrgOwner\", fields: [ownerId], references: [id], onDelete: Cascade)\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Relations\n members OrgMember[]\n apiKeys ApiKey[]\n patients Patient[]\n scans Scan[]\n auditLogs AuditLog[]\n}\n\nmodel OrgMember {\n id String @id @default(uuid())\n\n orgId String\n org Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)\n\n userId String @unique\n user User @relation(\"OrgMember\", fields: [userId], references: [id], onDelete: Cascade)\n\n isActive Boolean @default(true)\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// Patient\nenum Gender {\n Male\n Female\n}\n\nmodel Patient {\n id String @id @default(uuid())\n cin String\n full_name String\n date_of_birth String\n gender Gender\n email String\n phone_number String\n\n createdById String?\n created_by User? @relation(fields: [createdById], references: [id], onDelete: Cascade)\n\n orgId String?\n organization Organization? @relation(fields: [orgId], references: [id], onDelete: Cascade)\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Relations\n scans Scan[]\n}\n\n// Scan\nenum Class {\n meningioma\n glioma\n pituitary\n notumor\n}\n\nenum Status {\n PROCESSING\n DONE\n FAILED\n}\n\nmodel Scan {\n id String @id @default(uuid())\n scan_code String @unique\n name String?\n notes String?\n class Class\n confidence_score Float\n all_scores Json\n status Status @default(PROCESSING)\n processing Float\n\n uploadedById String\n uploaded_by User @relation(fields: [uploadedById], references: [id], onDelete: Cascade)\n\n patientId String?\n patient Patient? @relation(fields: [patientId], references: [id], onDelete: Cascade)\n\n orgId String?\n organization Organization? @relation(fields: [orgId], references: [id], onDelete: Cascade)\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Relations\n scanImage ScanImage?\n report Report?\n}\n\nmodel ScanImage {\n id String @id @default(uuid())\n scanId String @unique\n scan Scan @relation(fields: [scanId], references: [id], onDelete: Cascade)\n url String\n size Int\n resolution String\n format String\n name String\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// Report\nmodel Report {\n id String @id @default(uuid())\n content Json\n\n scanId String @unique\n scan Scan @relation(fields: [scanId], references: [id], onDelete: Cascade)\n\n code String @unique\n is_shared Boolean @default(false)\n downloads Int @default(0)\n share_token String? @unique\n processing Float\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// Notification\nenum NotificationType {\n scan\n report\n team\n alert\n info\n}\n\nmodel Notifications {\n id String @id @default(uuid())\n userId String\n title String\n message String\n path String?\n type NotificationType\n read Boolean @default(false)\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n}\n\nmodel EmailNotification {\n id String @id @default(uuid())\n\n userId String @unique\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n\n scanReady Boolean @default(true)\n reportReady Boolean @default(true)\n productUpdates Boolean @default(true)\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\nmodel InAppNotification {\n id String @id @default(uuid())\n\n userId String @unique\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n\n scanReady Boolean @default(true)\n reportReady Boolean @default(true)\n productUpdates Boolean @default(true)\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// Integration\nmodel ApiKey {\n id String @id @default(uuid())\n\n organizationId String\n organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)\n\n name String\n key String @unique\n lastUsedAt DateTime?\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// Session\nmodel Session {\n id String @id @default(uuid())\n\n userId String\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n\n refreshToken String @unique\n deviceInfo String?\n ipAddress String?\n lastUsedAt DateTime @default(now())\n expiresAt DateTime\n isRevoked Boolean @default(false)\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// Stripe\nenum SubscriptionStatus {\n active\n past_due\n canceled\n unpaid\n}\n\nmodel Subscription {\n id String @id @default(uuid())\n userId String @unique\n stripeCustomerId String\n stripeSubscriptionId String\n status SubscriptionStatus\n currentPeriodEnd DateTime\n cancelAtPeriodEnd Boolean @default(false)\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n}\n\nenum PaymentStatus {\n succeeded\n failed\n}\n\nenum PaymentMode {\n subscription\n renewal\n}\n\nmodel Payment {\n id String @id @default(uuid())\n userId String\n amount Int\n status PaymentStatus\n stripePaymentId String\n plan Plan\n mode PaymentMode\n createdAt DateTime @default(now())\n\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n}\n\n// Audit Logs\nenum AuditCategory {\n scans\n patients\n members\n api\n reports\n}\n\nenum AuditSeverity {\n info\n success\n warning\n danger\n}\n\nenum AuditStatus {\n success\n failed\n}\n\nmodel AuditLog {\n id String @id @default(uuid())\n\n orgId String\n organization Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)\n\n actorId String?\n actor User? @relation(fields: [actorId], references: [id], onDelete: SetNull)\n actorName String\n actorEmail String\n\n action String\n category AuditCategory\n status AuditStatus @default(success)\n severity AuditSeverity @default(info)\n\n target String\n targetId String?\n\n ip String?\n userAgent String?\n\n createdAt DateTime @default(now())\n\n @@index([orgId, createdAt])\n @@index([orgId, category])\n @@index([orgId, status])\n @@index([orgId, actorEmail])\n}\n", + "inlineSchema": "datasource db {\n provider = \"postgresql\"\n}\n\ngenerator client {\n provider = \"prisma-client\"\n output = \"./generated/client\"\n moduleFormat = \"cjs\"\n}\n\n// User\nenum Role {\n USER\n SUPER_ADMIN\n}\n\nenum Plan {\n FREE\n DOCTOR\n ORGANIZATION\n}\n\nmodel User {\n id String @id @default(uuid())\n username String @unique\n email String @unique\n password String?\n googleId String? @unique\n profile_image_url String?\n plan Plan @default(FREE)\n role Role @default(USER)\n is_active Boolean @default(true)\n\n total_scans Int @default(0)\n total_reports Int @default(0)\n\n twoFactorSecret String?\n twoFactorEnabled Boolean @default(false)\n\n reset_password_token String?\n reset_token_expires DateTime?\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Relations\n patients Patient[]\n scans Scan[]\n notifications Notifications[]\n emailNotification EmailNotification?\n inAppNotification InAppNotification?\n sessions Session[]\n\n ownedOrg Organization? @relation(\"OrgOwner\")\n orgMember OrgMember? @relation(\"OrgMember\")\n\n subscription Subscription?\n payments Payment[]\n\n auditLogs AuditLog[]\n\n submittedTickets Ticket[] @relation(\"TicketSubmittedBy\")\n assignedTickets Ticket[] @relation(\"TicketAssignedTo\")\n}\n\n// HOSPITAL\nmodel Organization {\n id String @id @default(uuid())\n name String\n ownerId String @unique\n owner User @relation(\"OrgOwner\", fields: [ownerId], references: [id], onDelete: Cascade)\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Relations\n members OrgMember[]\n apiKeys ApiKey[]\n patients Patient[]\n scans Scan[]\n auditLogs AuditLog[]\n}\n\nmodel OrgMember {\n id String @id @default(uuid())\n\n orgId String\n org Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)\n\n userId String @unique\n user User @relation(\"OrgMember\", fields: [userId], references: [id], onDelete: Cascade)\n\n isActive Boolean @default(true)\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// Patient\nenum Gender {\n Male\n Female\n}\n\nmodel Patient {\n id String @id @default(uuid())\n cin String\n full_name String\n date_of_birth String\n gender Gender\n email String\n phone_number String\n\n createdById String?\n created_by User? @relation(fields: [createdById], references: [id], onDelete: Cascade)\n\n orgId String?\n organization Organization? @relation(fields: [orgId], references: [id], onDelete: Cascade)\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Relations\n scans Scan[]\n}\n\n// Scan\nenum Class {\n meningioma\n glioma\n pituitary\n notumor\n}\n\nenum Status {\n PROCESSING\n DONE\n FAILED\n}\n\nmodel Scan {\n id String @id @default(uuid())\n scan_code String @unique\n name String?\n notes String?\n class Class\n confidence_score Float\n all_scores Json\n status Status @default(PROCESSING)\n processing Float\n\n uploadedById String\n uploaded_by User @relation(fields: [uploadedById], references: [id], onDelete: Cascade)\n\n patientId String?\n patient Patient? @relation(fields: [patientId], references: [id], onDelete: Cascade)\n\n orgId String?\n organization Organization? @relation(fields: [orgId], references: [id], onDelete: Cascade)\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Relations\n scanImage ScanImage?\n report Report?\n\n ticketsForScan Ticket[] @relation(\"TicketScan\")\n ticketsAsReanalysis Ticket[] @relation(\"TicketReanalysisScan\")\n}\n\nmodel ScanImage {\n id String @id @default(uuid())\n scanId String @unique\n scan Scan @relation(fields: [scanId], references: [id], onDelete: Cascade)\n url String\n size Int\n resolution String\n format String\n name String\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// Report\nmodel Report {\n id String @id @default(uuid())\n content Json\n\n scanId String @unique\n scan Scan @relation(fields: [scanId], references: [id], onDelete: Cascade)\n\n code String @unique\n is_shared Boolean @default(false)\n downloads Int @default(0)\n share_token String? @unique\n processing Float\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n ticketsForReport Ticket[] @relation(\"TicketReport\")\n ticketsAsReanalysis Ticket[] @relation(\"TicketReanalysisReport\")\n}\n\n// Notification\nenum NotificationType {\n scan\n report\n team\n alert\n info\n}\n\nmodel Notifications {\n id String @id @default(uuid())\n userId String\n title String\n message String\n path String?\n type NotificationType\n read Boolean @default(false)\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n}\n\nmodel EmailNotification {\n id String @id @default(uuid())\n\n userId String @unique\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n\n scanReady Boolean @default(true)\n reportReady Boolean @default(true)\n productUpdates Boolean @default(true)\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\nmodel InAppNotification {\n id String @id @default(uuid())\n\n userId String @unique\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n\n scanReady Boolean @default(true)\n reportReady Boolean @default(true)\n productUpdates Boolean @default(true)\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// Integration\nmodel ApiKey {\n id String @id @default(uuid())\n\n organizationId String\n organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)\n\n name String\n key String @unique\n lastUsedAt DateTime?\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// Session\nmodel Session {\n id String @id @default(uuid())\n\n userId String\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n\n refreshToken String @unique\n deviceInfo String?\n ipAddress String?\n lastUsedAt DateTime @default(now())\n expiresAt DateTime\n isRevoked Boolean @default(false)\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\n// Stripe\nenum SubscriptionStatus {\n active\n past_due\n canceled\n unpaid\n}\n\nmodel Subscription {\n id String @id @default(uuid())\n userId String @unique\n stripeCustomerId String\n stripeSubscriptionId String\n status SubscriptionStatus\n currentPeriodEnd DateTime\n cancelAtPeriodEnd Boolean @default(false)\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n}\n\nenum PaymentStatus {\n succeeded\n failed\n}\n\nenum PaymentMode {\n subscription\n renewal\n}\n\nmodel Payment {\n id String @id @default(uuid())\n userId String\n amount Int\n status PaymentStatus\n stripePaymentId String\n plan Plan\n mode PaymentMode\n createdAt DateTime @default(now())\n\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n}\n\n// Tickets\nenum TicketType {\n RE_ANALYSIS\n RE_REPORT\n}\n\nenum TicketStatus {\n OPEN\n IN_PROGRESS\n RESOLVED\n DISMISSED\n}\n\nenum TicketPriority {\n LOW\n MEDIUM\n HIGH\n}\n\nmodel Ticket {\n id String @id @default(uuid())\n code String @unique\n type TicketType\n status TicketStatus @default(OPEN)\n priority TicketPriority @default(MEDIUM)\n reason String\n\n scanId String?\n scan Scan? @relation(\"TicketScan\", fields: [scanId], references: [id], onDelete: SetNull)\n\n reportId String?\n report Report? @relation(\"TicketReport\", fields: [reportId], references: [id], onDelete: SetNull)\n\n submittedById String\n submittedBy User @relation(\"TicketSubmittedBy\", fields: [submittedById], references: [id], onDelete: Cascade)\n\n assignedToId String?\n assignedTo User? @relation(\"TicketAssignedTo\", fields: [assignedToId], references: [id], onDelete: SetNull)\n\n resolutionNote String?\n reanalysisScanId String?\n reanalysisScan Scan? @relation(\"TicketReanalysisScan\", fields: [reanalysisScanId], references: [id], onDelete: SetNull)\n reanalysisReportId String?\n reanalysisReport Report? @relation(\"TicketReanalysisReport\", fields: [reanalysisReportId], references: [id], onDelete: SetNull)\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n resolvedAt DateTime?\n\n @@index([status])\n @@index([type])\n @@index([submittedById])\n @@index([createdAt])\n}\n\n// Audit Logs\nenum AuditCategory {\n scans\n patients\n members\n api\n reports\n}\n\nenum AuditSeverity {\n info\n success\n warning\n danger\n}\n\nenum AuditStatus {\n success\n failed\n}\n\nmodel AuditLog {\n id String @id @default(uuid())\n\n orgId String?\n organization Organization? @relation(fields: [orgId], references: [id], onDelete: Cascade)\n\n actorId String?\n actor User? @relation(fields: [actorId], references: [id], onDelete: SetNull)\n actorName String\n actorEmail String\n\n action String\n category AuditCategory\n status AuditStatus @default(success)\n severity AuditSeverity @default(info)\n\n target String\n targetId String?\n\n ip String?\n userAgent String?\n\n createdAt DateTime @default(now())\n\n @@index([orgId, createdAt])\n @@index([orgId, category])\n @@index([orgId, status])\n @@index([orgId, actorEmail])\n}\n", "runtimeDataModel": { "models": {}, "enums": {}, @@ -32,10 +32,10 @@ const config: runtime.GetPrismaClientConfig = { } } -config.runtimeDataModel = JSON.parse("{\"models\":{\"User\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"username\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"email\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"password\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"googleId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"profile_image_url\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"plan\",\"kind\":\"enum\",\"type\":\"Plan\"},{\"name\":\"role\",\"kind\":\"enum\",\"type\":\"Role\"},{\"name\":\"is_active\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"total_scans\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"total_reports\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"twoFactorSecret\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"twoFactorEnabled\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"reset_password_token\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"reset_token_expires\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"patients\",\"kind\":\"object\",\"type\":\"Patient\",\"relationName\":\"PatientToUser\"},{\"name\":\"scans\",\"kind\":\"object\",\"type\":\"Scan\",\"relationName\":\"ScanToUser\"},{\"name\":\"notifications\",\"kind\":\"object\",\"type\":\"Notifications\",\"relationName\":\"NotificationsToUser\"},{\"name\":\"emailNotification\",\"kind\":\"object\",\"type\":\"EmailNotification\",\"relationName\":\"EmailNotificationToUser\"},{\"name\":\"inAppNotification\",\"kind\":\"object\",\"type\":\"InAppNotification\",\"relationName\":\"InAppNotificationToUser\"},{\"name\":\"sessions\",\"kind\":\"object\",\"type\":\"Session\",\"relationName\":\"SessionToUser\"},{\"name\":\"ownedOrg\",\"kind\":\"object\",\"type\":\"Organization\",\"relationName\":\"OrgOwner\"},{\"name\":\"orgMember\",\"kind\":\"object\",\"type\":\"OrgMember\",\"relationName\":\"OrgMember\"},{\"name\":\"subscription\",\"kind\":\"object\",\"type\":\"Subscription\",\"relationName\":\"SubscriptionToUser\"},{\"name\":\"payments\",\"kind\":\"object\",\"type\":\"Payment\",\"relationName\":\"PaymentToUser\"},{\"name\":\"auditLogs\",\"kind\":\"object\",\"type\":\"AuditLog\",\"relationName\":\"AuditLogToUser\"}],\"dbName\":null},\"Organization\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"ownerId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"owner\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"OrgOwner\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"members\",\"kind\":\"object\",\"type\":\"OrgMember\",\"relationName\":\"OrgMemberToOrganization\"},{\"name\":\"apiKeys\",\"kind\":\"object\",\"type\":\"ApiKey\",\"relationName\":\"ApiKeyToOrganization\"},{\"name\":\"patients\",\"kind\":\"object\",\"type\":\"Patient\",\"relationName\":\"OrganizationToPatient\"},{\"name\":\"scans\",\"kind\":\"object\",\"type\":\"Scan\",\"relationName\":\"OrganizationToScan\"},{\"name\":\"auditLogs\",\"kind\":\"object\",\"type\":\"AuditLog\",\"relationName\":\"AuditLogToOrganization\"}],\"dbName\":null},\"OrgMember\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"orgId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"org\",\"kind\":\"object\",\"type\":\"Organization\",\"relationName\":\"OrgMemberToOrganization\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"OrgMember\"},{\"name\":\"isActive\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"Patient\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"cin\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"full_name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"date_of_birth\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"gender\",\"kind\":\"enum\",\"type\":\"Gender\"},{\"name\":\"email\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"phone_number\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdById\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"created_by\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"PatientToUser\"},{\"name\":\"orgId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"organization\",\"kind\":\"object\",\"type\":\"Organization\",\"relationName\":\"OrganizationToPatient\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"scans\",\"kind\":\"object\",\"type\":\"Scan\",\"relationName\":\"PatientToScan\"}],\"dbName\":null},\"Scan\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"scan_code\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"notes\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"class\",\"kind\":\"enum\",\"type\":\"Class\"},{\"name\":\"confidence_score\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"all_scores\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"Status\"},{\"name\":\"processing\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"uploadedById\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"uploaded_by\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"ScanToUser\"},{\"name\":\"patientId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"patient\",\"kind\":\"object\",\"type\":\"Patient\",\"relationName\":\"PatientToScan\"},{\"name\":\"orgId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"organization\",\"kind\":\"object\",\"type\":\"Organization\",\"relationName\":\"OrganizationToScan\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"scanImage\",\"kind\":\"object\",\"type\":\"ScanImage\",\"relationName\":\"ScanToScanImage\"},{\"name\":\"report\",\"kind\":\"object\",\"type\":\"Report\",\"relationName\":\"ReportToScan\"}],\"dbName\":null},\"ScanImage\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"scanId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"scan\",\"kind\":\"object\",\"type\":\"Scan\",\"relationName\":\"ScanToScanImage\"},{\"name\":\"url\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"size\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"resolution\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"format\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"Report\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"content\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"scanId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"scan\",\"kind\":\"object\",\"type\":\"Scan\",\"relationName\":\"ReportToScan\"},{\"name\":\"code\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"is_shared\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"downloads\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"share_token\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"processing\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"Notifications\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"title\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"message\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"path\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"type\",\"kind\":\"enum\",\"type\":\"NotificationType\"},{\"name\":\"read\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"NotificationsToUser\"}],\"dbName\":null},\"EmailNotification\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"EmailNotificationToUser\"},{\"name\":\"scanReady\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"reportReady\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"productUpdates\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"InAppNotification\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"InAppNotificationToUser\"},{\"name\":\"scanReady\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"reportReady\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"productUpdates\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"ApiKey\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"organizationId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"organization\",\"kind\":\"object\",\"type\":\"Organization\",\"relationName\":\"ApiKeyToOrganization\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"key\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"lastUsedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"Session\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"SessionToUser\"},{\"name\":\"refreshToken\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"deviceInfo\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"ipAddress\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"lastUsedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"expiresAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"isRevoked\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"Subscription\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"stripeCustomerId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"stripeSubscriptionId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"SubscriptionStatus\"},{\"name\":\"currentPeriodEnd\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"cancelAtPeriodEnd\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"SubscriptionToUser\"}],\"dbName\":null},\"Payment\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"amount\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"PaymentStatus\"},{\"name\":\"stripePaymentId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"plan\",\"kind\":\"enum\",\"type\":\"Plan\"},{\"name\":\"mode\",\"kind\":\"enum\",\"type\":\"PaymentMode\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"PaymentToUser\"}],\"dbName\":null},\"AuditLog\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"orgId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"organization\",\"kind\":\"object\",\"type\":\"Organization\",\"relationName\":\"AuditLogToOrganization\"},{\"name\":\"actorId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"actor\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"AuditLogToUser\"},{\"name\":\"actorName\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"actorEmail\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"action\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"category\",\"kind\":\"enum\",\"type\":\"AuditCategory\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"AuditStatus\"},{\"name\":\"severity\",\"kind\":\"enum\",\"type\":\"AuditSeverity\"},{\"name\":\"target\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"targetId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"ip\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userAgent\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null}},\"enums\":{},\"types\":{}}") +config.runtimeDataModel = JSON.parse("{\"models\":{\"User\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"username\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"email\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"password\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"googleId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"profile_image_url\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"plan\",\"kind\":\"enum\",\"type\":\"Plan\"},{\"name\":\"role\",\"kind\":\"enum\",\"type\":\"Role\"},{\"name\":\"is_active\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"total_scans\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"total_reports\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"twoFactorSecret\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"twoFactorEnabled\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"reset_password_token\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"reset_token_expires\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"patients\",\"kind\":\"object\",\"type\":\"Patient\",\"relationName\":\"PatientToUser\"},{\"name\":\"scans\",\"kind\":\"object\",\"type\":\"Scan\",\"relationName\":\"ScanToUser\"},{\"name\":\"notifications\",\"kind\":\"object\",\"type\":\"Notifications\",\"relationName\":\"NotificationsToUser\"},{\"name\":\"emailNotification\",\"kind\":\"object\",\"type\":\"EmailNotification\",\"relationName\":\"EmailNotificationToUser\"},{\"name\":\"inAppNotification\",\"kind\":\"object\",\"type\":\"InAppNotification\",\"relationName\":\"InAppNotificationToUser\"},{\"name\":\"sessions\",\"kind\":\"object\",\"type\":\"Session\",\"relationName\":\"SessionToUser\"},{\"name\":\"ownedOrg\",\"kind\":\"object\",\"type\":\"Organization\",\"relationName\":\"OrgOwner\"},{\"name\":\"orgMember\",\"kind\":\"object\",\"type\":\"OrgMember\",\"relationName\":\"OrgMember\"},{\"name\":\"subscription\",\"kind\":\"object\",\"type\":\"Subscription\",\"relationName\":\"SubscriptionToUser\"},{\"name\":\"payments\",\"kind\":\"object\",\"type\":\"Payment\",\"relationName\":\"PaymentToUser\"},{\"name\":\"auditLogs\",\"kind\":\"object\",\"type\":\"AuditLog\",\"relationName\":\"AuditLogToUser\"},{\"name\":\"submittedTickets\",\"kind\":\"object\",\"type\":\"Ticket\",\"relationName\":\"TicketSubmittedBy\"},{\"name\":\"assignedTickets\",\"kind\":\"object\",\"type\":\"Ticket\",\"relationName\":\"TicketAssignedTo\"}],\"dbName\":null},\"Organization\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"ownerId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"owner\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"OrgOwner\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"members\",\"kind\":\"object\",\"type\":\"OrgMember\",\"relationName\":\"OrgMemberToOrganization\"},{\"name\":\"apiKeys\",\"kind\":\"object\",\"type\":\"ApiKey\",\"relationName\":\"ApiKeyToOrganization\"},{\"name\":\"patients\",\"kind\":\"object\",\"type\":\"Patient\",\"relationName\":\"OrganizationToPatient\"},{\"name\":\"scans\",\"kind\":\"object\",\"type\":\"Scan\",\"relationName\":\"OrganizationToScan\"},{\"name\":\"auditLogs\",\"kind\":\"object\",\"type\":\"AuditLog\",\"relationName\":\"AuditLogToOrganization\"}],\"dbName\":null},\"OrgMember\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"orgId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"org\",\"kind\":\"object\",\"type\":\"Organization\",\"relationName\":\"OrgMemberToOrganization\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"OrgMember\"},{\"name\":\"isActive\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"Patient\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"cin\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"full_name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"date_of_birth\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"gender\",\"kind\":\"enum\",\"type\":\"Gender\"},{\"name\":\"email\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"phone_number\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdById\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"created_by\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"PatientToUser\"},{\"name\":\"orgId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"organization\",\"kind\":\"object\",\"type\":\"Organization\",\"relationName\":\"OrganizationToPatient\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"scans\",\"kind\":\"object\",\"type\":\"Scan\",\"relationName\":\"PatientToScan\"}],\"dbName\":null},\"Scan\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"scan_code\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"notes\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"class\",\"kind\":\"enum\",\"type\":\"Class\"},{\"name\":\"confidence_score\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"all_scores\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"Status\"},{\"name\":\"processing\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"uploadedById\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"uploaded_by\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"ScanToUser\"},{\"name\":\"patientId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"patient\",\"kind\":\"object\",\"type\":\"Patient\",\"relationName\":\"PatientToScan\"},{\"name\":\"orgId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"organization\",\"kind\":\"object\",\"type\":\"Organization\",\"relationName\":\"OrganizationToScan\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"scanImage\",\"kind\":\"object\",\"type\":\"ScanImage\",\"relationName\":\"ScanToScanImage\"},{\"name\":\"report\",\"kind\":\"object\",\"type\":\"Report\",\"relationName\":\"ReportToScan\"},{\"name\":\"ticketsForScan\",\"kind\":\"object\",\"type\":\"Ticket\",\"relationName\":\"TicketScan\"},{\"name\":\"ticketsAsReanalysis\",\"kind\":\"object\",\"type\":\"Ticket\",\"relationName\":\"TicketReanalysisScan\"}],\"dbName\":null},\"ScanImage\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"scanId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"scan\",\"kind\":\"object\",\"type\":\"Scan\",\"relationName\":\"ScanToScanImage\"},{\"name\":\"url\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"size\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"resolution\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"format\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"Report\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"content\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"scanId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"scan\",\"kind\":\"object\",\"type\":\"Scan\",\"relationName\":\"ReportToScan\"},{\"name\":\"code\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"is_shared\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"downloads\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"share_token\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"processing\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"ticketsForReport\",\"kind\":\"object\",\"type\":\"Ticket\",\"relationName\":\"TicketReport\"},{\"name\":\"ticketsAsReanalysis\",\"kind\":\"object\",\"type\":\"Ticket\",\"relationName\":\"TicketReanalysisReport\"}],\"dbName\":null},\"Notifications\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"title\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"message\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"path\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"type\",\"kind\":\"enum\",\"type\":\"NotificationType\"},{\"name\":\"read\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"NotificationsToUser\"}],\"dbName\":null},\"EmailNotification\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"EmailNotificationToUser\"},{\"name\":\"scanReady\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"reportReady\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"productUpdates\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"InAppNotification\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"InAppNotificationToUser\"},{\"name\":\"scanReady\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"reportReady\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"productUpdates\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"ApiKey\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"organizationId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"organization\",\"kind\":\"object\",\"type\":\"Organization\",\"relationName\":\"ApiKeyToOrganization\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"key\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"lastUsedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"Session\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"SessionToUser\"},{\"name\":\"refreshToken\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"deviceInfo\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"ipAddress\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"lastUsedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"expiresAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"isRevoked\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"Subscription\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"stripeCustomerId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"stripeSubscriptionId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"SubscriptionStatus\"},{\"name\":\"currentPeriodEnd\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"cancelAtPeriodEnd\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"SubscriptionToUser\"}],\"dbName\":null},\"Payment\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"amount\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"PaymentStatus\"},{\"name\":\"stripePaymentId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"plan\",\"kind\":\"enum\",\"type\":\"Plan\"},{\"name\":\"mode\",\"kind\":\"enum\",\"type\":\"PaymentMode\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"PaymentToUser\"}],\"dbName\":null},\"Ticket\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"code\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"type\",\"kind\":\"enum\",\"type\":\"TicketType\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"TicketStatus\"},{\"name\":\"priority\",\"kind\":\"enum\",\"type\":\"TicketPriority\"},{\"name\":\"reason\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"scanId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"scan\",\"kind\":\"object\",\"type\":\"Scan\",\"relationName\":\"TicketScan\"},{\"name\":\"reportId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"report\",\"kind\":\"object\",\"type\":\"Report\",\"relationName\":\"TicketReport\"},{\"name\":\"submittedById\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"submittedBy\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"TicketSubmittedBy\"},{\"name\":\"assignedToId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"assignedTo\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"TicketAssignedTo\"},{\"name\":\"resolutionNote\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"reanalysisScanId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"reanalysisScan\",\"kind\":\"object\",\"type\":\"Scan\",\"relationName\":\"TicketReanalysisScan\"},{\"name\":\"reanalysisReportId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"reanalysisReport\",\"kind\":\"object\",\"type\":\"Report\",\"relationName\":\"TicketReanalysisReport\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"resolvedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"AuditLog\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"orgId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"organization\",\"kind\":\"object\",\"type\":\"Organization\",\"relationName\":\"AuditLogToOrganization\"},{\"name\":\"actorId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"actor\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"AuditLogToUser\"},{\"name\":\"actorName\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"actorEmail\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"action\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"category\",\"kind\":\"enum\",\"type\":\"AuditCategory\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"AuditStatus\"},{\"name\":\"severity\",\"kind\":\"enum\",\"type\":\"AuditSeverity\"},{\"name\":\"target\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"targetId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"ip\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userAgent\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null}},\"enums\":{},\"types\":{}}") config.parameterizationSchema = { - strings: JSON.parse("[\"where\",\"orderBy\",\"cursor\",\"created_by\",\"owner\",\"org\",\"user\",\"members\",\"organization\",\"apiKeys\",\"patients\",\"uploaded_by\",\"patient\",\"scan\",\"scanImage\",\"report\",\"scans\",\"actor\",\"auditLogs\",\"_count\",\"notifications\",\"emailNotification\",\"inAppNotification\",\"sessions\",\"ownedOrg\",\"orgMember\",\"subscription\",\"payments\",\"User.findUnique\",\"User.findUniqueOrThrow\",\"User.findFirst\",\"User.findFirstOrThrow\",\"User.findMany\",\"data\",\"User.createOne\",\"User.createMany\",\"User.createManyAndReturn\",\"User.updateOne\",\"User.updateMany\",\"User.updateManyAndReturn\",\"create\",\"update\",\"User.upsertOne\",\"User.deleteOne\",\"User.deleteMany\",\"having\",\"_avg\",\"_sum\",\"_min\",\"_max\",\"User.groupBy\",\"User.aggregate\",\"Organization.findUnique\",\"Organization.findUniqueOrThrow\",\"Organization.findFirst\",\"Organization.findFirstOrThrow\",\"Organization.findMany\",\"Organization.createOne\",\"Organization.createMany\",\"Organization.createManyAndReturn\",\"Organization.updateOne\",\"Organization.updateMany\",\"Organization.updateManyAndReturn\",\"Organization.upsertOne\",\"Organization.deleteOne\",\"Organization.deleteMany\",\"Organization.groupBy\",\"Organization.aggregate\",\"OrgMember.findUnique\",\"OrgMember.findUniqueOrThrow\",\"OrgMember.findFirst\",\"OrgMember.findFirstOrThrow\",\"OrgMember.findMany\",\"OrgMember.createOne\",\"OrgMember.createMany\",\"OrgMember.createManyAndReturn\",\"OrgMember.updateOne\",\"OrgMember.updateMany\",\"OrgMember.updateManyAndReturn\",\"OrgMember.upsertOne\",\"OrgMember.deleteOne\",\"OrgMember.deleteMany\",\"OrgMember.groupBy\",\"OrgMember.aggregate\",\"Patient.findUnique\",\"Patient.findUniqueOrThrow\",\"Patient.findFirst\",\"Patient.findFirstOrThrow\",\"Patient.findMany\",\"Patient.createOne\",\"Patient.createMany\",\"Patient.createManyAndReturn\",\"Patient.updateOne\",\"Patient.updateMany\",\"Patient.updateManyAndReturn\",\"Patient.upsertOne\",\"Patient.deleteOne\",\"Patient.deleteMany\",\"Patient.groupBy\",\"Patient.aggregate\",\"Scan.findUnique\",\"Scan.findUniqueOrThrow\",\"Scan.findFirst\",\"Scan.findFirstOrThrow\",\"Scan.findMany\",\"Scan.createOne\",\"Scan.createMany\",\"Scan.createManyAndReturn\",\"Scan.updateOne\",\"Scan.updateMany\",\"Scan.updateManyAndReturn\",\"Scan.upsertOne\",\"Scan.deleteOne\",\"Scan.deleteMany\",\"Scan.groupBy\",\"Scan.aggregate\",\"ScanImage.findUnique\",\"ScanImage.findUniqueOrThrow\",\"ScanImage.findFirst\",\"ScanImage.findFirstOrThrow\",\"ScanImage.findMany\",\"ScanImage.createOne\",\"ScanImage.createMany\",\"ScanImage.createManyAndReturn\",\"ScanImage.updateOne\",\"ScanImage.updateMany\",\"ScanImage.updateManyAndReturn\",\"ScanImage.upsertOne\",\"ScanImage.deleteOne\",\"ScanImage.deleteMany\",\"ScanImage.groupBy\",\"ScanImage.aggregate\",\"Report.findUnique\",\"Report.findUniqueOrThrow\",\"Report.findFirst\",\"Report.findFirstOrThrow\",\"Report.findMany\",\"Report.createOne\",\"Report.createMany\",\"Report.createManyAndReturn\",\"Report.updateOne\",\"Report.updateMany\",\"Report.updateManyAndReturn\",\"Report.upsertOne\",\"Report.deleteOne\",\"Report.deleteMany\",\"Report.groupBy\",\"Report.aggregate\",\"Notifications.findUnique\",\"Notifications.findUniqueOrThrow\",\"Notifications.findFirst\",\"Notifications.findFirstOrThrow\",\"Notifications.findMany\",\"Notifications.createOne\",\"Notifications.createMany\",\"Notifications.createManyAndReturn\",\"Notifications.updateOne\",\"Notifications.updateMany\",\"Notifications.updateManyAndReturn\",\"Notifications.upsertOne\",\"Notifications.deleteOne\",\"Notifications.deleteMany\",\"Notifications.groupBy\",\"Notifications.aggregate\",\"EmailNotification.findUnique\",\"EmailNotification.findUniqueOrThrow\",\"EmailNotification.findFirst\",\"EmailNotification.findFirstOrThrow\",\"EmailNotification.findMany\",\"EmailNotification.createOne\",\"EmailNotification.createMany\",\"EmailNotification.createManyAndReturn\",\"EmailNotification.updateOne\",\"EmailNotification.updateMany\",\"EmailNotification.updateManyAndReturn\",\"EmailNotification.upsertOne\",\"EmailNotification.deleteOne\",\"EmailNotification.deleteMany\",\"EmailNotification.groupBy\",\"EmailNotification.aggregate\",\"InAppNotification.findUnique\",\"InAppNotification.findUniqueOrThrow\",\"InAppNotification.findFirst\",\"InAppNotification.findFirstOrThrow\",\"InAppNotification.findMany\",\"InAppNotification.createOne\",\"InAppNotification.createMany\",\"InAppNotification.createManyAndReturn\",\"InAppNotification.updateOne\",\"InAppNotification.updateMany\",\"InAppNotification.updateManyAndReturn\",\"InAppNotification.upsertOne\",\"InAppNotification.deleteOne\",\"InAppNotification.deleteMany\",\"InAppNotification.groupBy\",\"InAppNotification.aggregate\",\"ApiKey.findUnique\",\"ApiKey.findUniqueOrThrow\",\"ApiKey.findFirst\",\"ApiKey.findFirstOrThrow\",\"ApiKey.findMany\",\"ApiKey.createOne\",\"ApiKey.createMany\",\"ApiKey.createManyAndReturn\",\"ApiKey.updateOne\",\"ApiKey.updateMany\",\"ApiKey.updateManyAndReturn\",\"ApiKey.upsertOne\",\"ApiKey.deleteOne\",\"ApiKey.deleteMany\",\"ApiKey.groupBy\",\"ApiKey.aggregate\",\"Session.findUnique\",\"Session.findUniqueOrThrow\",\"Session.findFirst\",\"Session.findFirstOrThrow\",\"Session.findMany\",\"Session.createOne\",\"Session.createMany\",\"Session.createManyAndReturn\",\"Session.updateOne\",\"Session.updateMany\",\"Session.updateManyAndReturn\",\"Session.upsertOne\",\"Session.deleteOne\",\"Session.deleteMany\",\"Session.groupBy\",\"Session.aggregate\",\"Subscription.findUnique\",\"Subscription.findUniqueOrThrow\",\"Subscription.findFirst\",\"Subscription.findFirstOrThrow\",\"Subscription.findMany\",\"Subscription.createOne\",\"Subscription.createMany\",\"Subscription.createManyAndReturn\",\"Subscription.updateOne\",\"Subscription.updateMany\",\"Subscription.updateManyAndReturn\",\"Subscription.upsertOne\",\"Subscription.deleteOne\",\"Subscription.deleteMany\",\"Subscription.groupBy\",\"Subscription.aggregate\",\"Payment.findUnique\",\"Payment.findUniqueOrThrow\",\"Payment.findFirst\",\"Payment.findFirstOrThrow\",\"Payment.findMany\",\"Payment.createOne\",\"Payment.createMany\",\"Payment.createManyAndReturn\",\"Payment.updateOne\",\"Payment.updateMany\",\"Payment.updateManyAndReturn\",\"Payment.upsertOne\",\"Payment.deleteOne\",\"Payment.deleteMany\",\"Payment.groupBy\",\"Payment.aggregate\",\"AuditLog.findUnique\",\"AuditLog.findUniqueOrThrow\",\"AuditLog.findFirst\",\"AuditLog.findFirstOrThrow\",\"AuditLog.findMany\",\"AuditLog.createOne\",\"AuditLog.createMany\",\"AuditLog.createManyAndReturn\",\"AuditLog.updateOne\",\"AuditLog.updateMany\",\"AuditLog.updateManyAndReturn\",\"AuditLog.upsertOne\",\"AuditLog.deleteOne\",\"AuditLog.deleteMany\",\"AuditLog.groupBy\",\"AuditLog.aggregate\",\"AND\",\"OR\",\"NOT\",\"id\",\"orgId\",\"actorId\",\"actorName\",\"actorEmail\",\"action\",\"AuditCategory\",\"category\",\"AuditStatus\",\"status\",\"AuditSeverity\",\"severity\",\"target\",\"targetId\",\"ip\",\"userAgent\",\"createdAt\",\"equals\",\"in\",\"notIn\",\"lt\",\"lte\",\"gt\",\"gte\",\"not\",\"contains\",\"startsWith\",\"endsWith\",\"userId\",\"amount\",\"PaymentStatus\",\"stripePaymentId\",\"Plan\",\"plan\",\"PaymentMode\",\"mode\",\"stripeCustomerId\",\"stripeSubscriptionId\",\"SubscriptionStatus\",\"currentPeriodEnd\",\"cancelAtPeriodEnd\",\"updatedAt\",\"refreshToken\",\"deviceInfo\",\"ipAddress\",\"lastUsedAt\",\"expiresAt\",\"isRevoked\",\"organizationId\",\"name\",\"key\",\"scanReady\",\"reportReady\",\"productUpdates\",\"title\",\"message\",\"path\",\"NotificationType\",\"type\",\"read\",\"content\",\"scanId\",\"code\",\"is_shared\",\"downloads\",\"share_token\",\"processing\",\"string_contains\",\"string_starts_with\",\"string_ends_with\",\"array_starts_with\",\"array_ends_with\",\"array_contains\",\"url\",\"size\",\"resolution\",\"format\",\"scan_code\",\"notes\",\"Class\",\"class\",\"confidence_score\",\"all_scores\",\"Status\",\"uploadedById\",\"patientId\",\"cin\",\"full_name\",\"date_of_birth\",\"Gender\",\"gender\",\"email\",\"phone_number\",\"createdById\",\"isActive\",\"ownerId\",\"every\",\"some\",\"none\",\"username\",\"password\",\"googleId\",\"profile_image_url\",\"Role\",\"role\",\"is_active\",\"total_scans\",\"total_reports\",\"twoFactorSecret\",\"twoFactorEnabled\",\"reset_password_token\",\"reset_token_expires\",\"is\",\"isNot\",\"connectOrCreate\",\"upsert\",\"disconnect\",\"delete\",\"connect\",\"createMany\",\"set\",\"updateMany\",\"deleteMany\",\"increment\",\"decrement\",\"multiply\",\"divide\"]"), - graph: "4geGAfABHwoAAP4DACAQAAD_AwAgEgAAgAQAIBQAAJ8EACAVAACgBAAgFgAAoQQAIBcAAKIEACAYAACXBAAgGQAAowQAIBoAAKQEACAbAAClBAAglAIAAJ0EADCVAgAABwAQlgIAAJ0EADCXAgEAAAABpwJAANIDACG4AgAAhwS4AiLAAkAA0gMAIfICAQAAAAH6AgEAAAAB-wIBAIoEACH8AgEAAAAB_QIBAIoEACH_AgAAngT_AiKAAyAA0wMAIYEDAgDpAwAhggMCAOkDACGDAwEAigQAIYQDIADTAwAhhQMBAIoEACGGA0AAmwQAIQEAAAABACARAwAAkgQAIAgAAJcEACAQAAD_AwAglAIAAKYEADCVAgAAAwAQlgIAAKYEADCXAgEA0AMAIZgCAQCKBAAhpwJAANIDACHAAkAA0gMAIe0CAQDQAwAh7gIBANADACHvAgEA0AMAIfECAACnBPECIvICAQDQAwAh8wIBANADACH0AgEAigQAIQUDAADIBAAgCAAA8QYAIBAAAPcFACCYAgAAqAQAIPQCAACoBAAgEQMAAJIEACAIAACXBAAgEAAA_wMAIJQCAACmBAAwlQIAAAMAEJYCAACmBAAwlwIBAAAAAZgCAQCKBAAhpwJAANIDACHAAkAA0gMAIe0CAQDQAwAh7gIBANADACHvAgEA0AMAIfECAACnBPECIvICAQDQAwAh8wIBANADACH0AgEAigQAIQMAAAADACABAAAEADACAAAFACAfCgAA_gMAIBAAAP8DACASAACABAAgFAAAnwQAIBUAAKAEACAWAAChBAAgFwAAogQAIBgAAJcEACAZAACjBAAgGgAApAQAIBsAAKUEACCUAgAAnQQAMJUCAAAHABCWAgAAnQQAMJcCAQDQAwAhpwJAANIDACG4AgAAhwS4AiLAAkAA0gMAIfICAQDQAwAh-gIBANADACH7AgEAigQAIfwCAQCKBAAh_QIBAIoEACH_AgAAngT_AiKAAyAA0wMAIYEDAgDpAwAhggMCAOkDACGDAwEAigQAIYQDIADTAwAhhQMBAIoEACGGA0AAmwQAIQEAAAAHACAOBAAA1AMAIAcAAPwDACAJAAD9AwAgCgAA_gMAIBAAAP8DACASAACABAAglAIAAPsDADCVAgAACQAQlgIAAPsDADCXAgEA0AMAIacCQADSAwAhwAJAANIDACHIAgEA0AMAIfYCAQDQAwAhAQAAAAkAIAsFAACRBAAgBgAA1AMAIJQCAACcBAAwlQIAAAsAEJYCAACcBAAwlwIBANADACGYAgEA0AMAIacCQADSAwAhswIBANADACHAAkAA0gMAIfUCIADTAwAhAgUAAPEGACAGAADIBAAgCwUAAJEEACAGAADUAwAglAIAAJwEADCVAgAACwAQlgIAAJwEADCXAgEAAAABmAIBANADACGnAkAA0gMAIbMCAQAAAAHAAkAA0gMAIfUCIADTAwAhAwAAAAsAIAEAAAwAMAIAAA0AIAsIAACRBAAglAIAAJoEADCVAgAADwAQlgIAAJoEADCXAgEA0AMAIacCQADSAwAhwAJAANIDACHEAkAAmwQAIccCAQDQAwAhyAIBANADACHJAgEA0AMAIQIIAADxBgAgxAIAAKgEACALCAAAkQQAIJQCAACaBAAwlQIAAA8AEJYCAACaBAAwlwIBAAAAAacCQADSAwAhwAJAANIDACHEAkAAmwQAIccCAQDQAwAhyAIBANADACHJAgEAAAABAwAAAA8AIAEAABAAMAIAABEAIAMAAAADACABAAAEADACAAAFACAWCAAAlwQAIAsAANQDACAMAACWBAAgDgAAmAQAIA8AAJkEACCUAgAAkwQAMJUCAAAUABCWAgAAkwQAMJcCAQDQAwAhmAIBAIoEACGgAgAAlQTrAiKnAkAA0gMAIcACQADSAwAhyAIBAIoEACHZAggA6gMAIeQCAQDQAwAh5QIBAIoEACHnAgAAlATnAiLoAggA6gMAIekCAADoAwAg6wIBANADACHsAgEAigQAIQkIAADxBgAgCwAAyAQAIAwAAPUGACAOAAD2BgAgDwAA9wYAIJgCAACoBAAgyAIAAKgEACDlAgAAqAQAIOwCAACoBAAgFggAAJcEACALAADUAwAgDAAAlgQAIA4AAJgEACAPAACZBAAglAIAAJMEADCVAgAAFAAQlgIAAJMEADCXAgEAAAABmAIBAIoEACGgAgAAlQTrAiKnAkAA0gMAIcACQADSAwAhyAIBAIoEACHZAggA6gMAIeQCAQAAAAHlAgEAigQAIecCAACUBOcCIugCCADqAwAh6QIAAOgDACDrAgEA0AMAIewCAQCKBAAhAwAAABQAIAEAABUAMAIAABYAIAEAAAADACABAAAACQAgDQ0AAOsDACCUAgAA7QMAMJUCAAAaABCWAgAA7QMAMJcCAQDQAwAhpwJAANIDACHAAkAA0gMAIcgCAQDQAwAh1AIBANADACHgAgEA0AMAIeECAgDpAwAh4gIBANADACHjAgEA0AMAIQEAAAAaACAODQAA6wMAIJQCAADnAwAwlQIAABwAEJYCAADnAwAwlwIBANADACGnAkAA0gMAIcACQADSAwAh0wIAAOgDACDUAgEA0AMAIdUCAQDQAwAh1gIgANMDACHXAgIA6QMAIdgCAQCKBAAh2QIIAOoDACEBAAAAHAAgEwgAAJEEACARAACSBAAglAIAAI0EADCVAgAAHgAQlgIAAI0EADCXAgEA0AMAIZgCAQDQAwAhmQIBAIoEACGaAgEA0AMAIZsCAQDQAwAhnAIBANADACGeAgAAjgSeAiKgAgAAjwSgAiKiAgAAkASiAiKjAgEA0AMAIaQCAQCKBAAhpQIBAIoEACGmAgEAigQAIacCQADSAwAhBggAAPEGACARAADIBAAgmQIAAKgEACCkAgAAqAQAIKUCAACoBAAgpgIAAKgEACATCAAAkQQAIBEAAJIEACCUAgAAjQQAMJUCAAAeABCWAgAAjQQAMJcCAQAAAAGYAgEA0AMAIZkCAQCKBAAhmgIBANADACGbAgEA0AMAIZwCAQDQAwAhngIAAI4EngIioAIAAI8EoAIiogIAAJAEogIiowIBANADACGkAgEAigQAIaUCAQCKBAAhpgIBAIoEACGnAkAA0gMAIQMAAAAeACABAAAfADACAAAgACABAAAABwAgAQAAAAsAIAEAAAAPACABAAAAAwAgAQAAABQAIAEAAAAeACADAAAAFAAgAQAAFQAwAgAAFgAgAQAAABQAIAMAAAAUACABAAAVADACAAAWACANBgAA1AMAIJQCAACLBAAwlQIAACsAEJYCAACLBAAwlwIBANADACGnAkAA0gMAIbMCAQDQAwAhwAJAANIDACHNAgEA0AMAIc4CAQDQAwAhzwIBAIoEACHRAgAAjATRAiLSAiAA0wMAIQIGAADIBAAgzwIAAKgEACANBgAA1AMAIJQCAACLBAAwlQIAACsAEJYCAACLBAAwlwIBAAAAAacCQADSAwAhswIBANADACHAAkAA0gMAIc0CAQDQAwAhzgIBANADACHPAgEAigQAIdECAACMBNECItICIADTAwAhAwAAACsAIAEAACwAMAIAAC0AIAsGAADUAwAglAIAAN0DADCVAgAALwAQlgIAAN0DADCXAgEA0AMAIacCQADSAwAhswIBANADACHAAkAA0gMAIcoCIADTAwAhywIgANMDACHMAiAA0wMAIQEAAAAvACALBgAA1AMAIJQCAADbAwAwlQIAADEAEJYCAADbAwAwlwIBANADACGnAkAA0gMAIbMCAQDQAwAhwAJAANIDACHKAiAA0wMAIcsCIADTAwAhzAIgANMDACEBAAAAMQAgDgYAANQDACCUAgAAiQQAMJUCAAAzABCWAgAAiQQAMJcCAQDQAwAhpwJAANIDACGzAgEA0AMAIcACQADSAwAhwQIBANADACHCAgEAigQAIcMCAQCKBAAhxAJAANIDACHFAkAA0gMAIcYCIADTAwAhAwYAAMgEACDCAgAAqAQAIMMCAACoBAAgDgYAANQDACCUAgAAiQQAMJUCAAAzABCWAgAAiQQAMJcCAQAAAAGnAkAA0gMAIbMCAQDQAwAhwAJAANIDACHBAgEAAAABwgIBAIoEACHDAgEAigQAIcQCQADSAwAhxQJAANIDACHGAiAA0wMAIQMAAAAzACABAAA0ADACAAA1ACABAAAACQAgAQAAAAsAIA0GAADUAwAglAIAAM8DADCVAgAAOQAQlgIAAM8DADCXAgEA0AMAIaACAADRA74CIqcCQADSAwAhswIBANADACG7AgEA0AMAIbwCAQDQAwAhvgJAANIDACG_AiAA0wMAIcACQADSAwAhAQAAADkAIAwGAADUAwAglAIAAIUEADCVAgAAOwAQlgIAAIUEADCXAgEA0AMAIaACAACGBLYCIqcCQADSAwAhswIBANADACG0AgIA6QMAIbYCAQDQAwAhuAIAAIcEuAIiugIAAIgEugIiAQYAAMgEACAMBgAA1AMAIJQCAACFBAAwlQIAADsAEJYCAACFBAAwlwIBAAAAAaACAACGBLYCIqcCQADSAwAhswIBANADACG0AgIA6QMAIbYCAQDQAwAhuAIAAIcEuAIiugIAAIgEugIiAwAAADsAIAEAADwAMAIAAD0AIAMAAAAeACABAAAfADACAAAgACABAAAAAwAgAQAAABQAIAEAAAArACABAAAAMwAgAQAAADsAIAEAAAAeACABAAAAAQAgEQoAAPYFACAQAAD3BQAgEgAA-AUAIBQAAO0GACAVAADuBgAgFgAA7wYAIBcAAPAGACAYAADxBgAgGQAA8gYAIBoAAPMGACAbAAD0BgAg-wIAAKgEACD8AgAAqAQAIP0CAACoBAAggwMAAKgEACCFAwAAqAQAIIYDAACoBAAgAwAAAAcAIAEAAEcAMAIAAAEAIAMAAAAHACABAABHADACAAABACADAAAABwAgAQAARwAwAgAAAQAgHAoAAOIGACAQAADjBgAgEgAA7AYAIBQAAOQGACAVAADlBgAgFgAA5gYAIBcAAOcGACAYAADoBgAgGQAA6QYAIBoAAOoGACAbAADrBgAglwIBAAAAAacCQAAAAAG4AgAAALgCAsACQAAAAAHyAgEAAAAB-gIBAAAAAfsCAQAAAAH8AgEAAAAB_QIBAAAAAf8CAAAA_wICgAMgAAAAAYEDAgAAAAGCAwIAAAABgwMBAAAAAYQDIAAAAAGFAwEAAAABhgNAAAAAAQEhAABLACARlwIBAAAAAacCQAAAAAG4AgAAALgCAsACQAAAAAHyAgEAAAAB-gIBAAAAAfsCAQAAAAH8AgEAAAAB_QIBAAAAAf8CAAAA_wICgAMgAAAAAYEDAgAAAAGCAwIAAAABgwMBAAAAAYQDIAAAAAGFAwEAAAABhgNAAAAAAQEhAABNADABIQAATQAwHAoAAP8FACAQAACABgAgEgAAiQYAIBQAAIEGACAVAACCBgAgFgAAgwYAIBcAAIQGACAYAACFBgAgGQAAhgYAIBoAAIcGACAbAACIBgAglwIBAKwEACGnAkAAsQQAIbgCAAC9BLgCIsACQACxBAAh8gIBAKwEACH6AgEArAQAIfsCAQCwBAAh_AIBALAEACH9AgEAsAQAIf8CAAD-Bf8CIoADIADFBAAhgQMCALsEACGCAwIAuwQAIYMDAQCwBAAhhAMgAMUEACGFAwEAsAQAIYYDQADRBAAhAgAAAAEAICEAAFAAIBGXAgEArAQAIacCQACxBAAhuAIAAL0EuAIiwAJAALEEACHyAgEArAQAIfoCAQCsBAAh-wIBALAEACH8AgEAsAQAIf0CAQCwBAAh_wIAAP4F_wIigAMgAMUEACGBAwIAuwQAIYIDAgC7BAAhgwMBALAEACGEAyAAxQQAIYUDAQCwBAAhhgNAANEEACECAAAABwAgIQAAUgAgAgAAAAcAICEAAFIAIAMAAAABACAoAABLACApAABQACABAAAAAQAgAQAAAAcAIAsTAAD5BQAgLgAA-gUAIC8AAP0FACAwAAD8BQAgMQAA-wUAIPsCAACoBAAg_AIAAKgEACD9AgAAqAQAIIMDAACoBAAghQMAAKgEACCGAwAAqAQAIBSUAgAAgQQAMJUCAABZABCWAgAAgQQAMJcCAQCnAwAhpwJAAKwDACG4AgAAvgO4AiLAAkAArAMAIfICAQCnAwAh-gIBAKcDACH7AgEAqAMAIfwCAQCoAwAh_QIBAKgDACH_AgAAggT_AiKAAyAAygMAIYEDAgC8AwAhggMCALwDACGDAwEAqAMAIYQDIADKAwAhhQMBAKgDACGGA0AA1wMAIQMAAAAHACABAABYADAtAABZACADAAAABwAgAQAARwAwAgAAAQAgDgQAANQDACAHAAD8AwAgCQAA_QMAIAoAAP4DACAQAAD_AwAgEgAAgAQAIJQCAAD7AwAwlQIAAAkAEJYCAAD7AwAwlwIBAAAAAacCQADSAwAhwAJAANIDACHIAgEA0AMAIfYCAQAAAAEBAAAAXAAgAQAAAFwAIAYEAADIBAAgBwAA9AUAIAkAAPUFACAKAAD2BQAgEAAA9wUAIBIAAPgFACADAAAACQAgAQAAXwAwAgAAXAAgAwAAAAkAIAEAAF8AMAIAAFwAIAMAAAAJACABAABfADACAABcACALBAAA7gUAIAcAAO8FACAJAADwBQAgCgAA8QUAIBAAAPIFACASAADzBQAglwIBAAAAAacCQAAAAAHAAkAAAAAByAIBAAAAAfYCAQAAAAEBIQAAYwAgBZcCAQAAAAGnAkAAAAABwAJAAAAAAcgCAQAAAAH2AgEAAAABASEAAGUAMAEhAABlADALBAAArwUAIAcAALAFACAJAACxBQAgCgAAsgUAIBAAALMFACASAAC0BQAglwIBAKwEACGnAkAAsQQAIcACQACxBAAhyAIBAKwEACH2AgEArAQAIQIAAABcACAhAABoACAFlwIBAKwEACGnAkAAsQQAIcACQACxBAAhyAIBAKwEACH2AgEArAQAIQIAAAAJACAhAABqACACAAAACQAgIQAAagAgAwAAAFwAICgAAGMAICkAAGgAIAEAAABcACABAAAACQAgAxMAAKwFACAwAACuBQAgMQAArQUAIAiUAgAA-gMAMJUCAABxABCWAgAA-gMAMJcCAQCnAwAhpwJAAKwDACHAAkAArAMAIcgCAQCnAwAh9gIBAKcDACEDAAAACQAgAQAAcAAwLQAAcQAgAwAAAAkAIAEAAF8AMAIAAFwAIAEAAAANACABAAAADQAgAwAAAAsAIAEAAAwAMAIAAA0AIAMAAAALACABAAAMADACAAANACADAAAACwAgAQAADAAwAgAADQAgCAUAAKoFACAGAACrBQAglwIBAAAAAZgCAQAAAAGnAkAAAAABswIBAAAAAcACQAAAAAH1AiAAAAABASEAAHkAIAaXAgEAAAABmAIBAAAAAacCQAAAAAGzAgEAAAABwAJAAAAAAfUCIAAAAAEBIQAAewAwASEAAHsAMAgFAACoBQAgBgAAqQUAIJcCAQCsBAAhmAIBAKwEACGnAkAAsQQAIbMCAQCsBAAhwAJAALEEACH1AiAAxQQAIQIAAAANACAhAAB-ACAGlwIBAKwEACGYAgEArAQAIacCQACxBAAhswIBAKwEACHAAkAAsQQAIfUCIADFBAAhAgAAAAsAICEAAIABACACAAAACwAgIQAAgAEAIAMAAAANACAoAAB5ACApAAB-ACABAAAADQAgAQAAAAsAIAMTAAClBQAgMAAApwUAIDEAAKYFACAJlAIAAPkDADCVAgAAhwEAEJYCAAD5AwAwlwIBAKcDACGYAgEApwMAIacCQACsAwAhswIBAKcDACHAAkAArAMAIfUCIADKAwAhAwAAAAsAIAEAAIYBADAtAACHAQAgAwAAAAsAIAEAAAwAMAIAAA0AIAEAAAAFACABAAAABQAgAwAAAAMAIAEAAAQAMAIAAAUAIAMAAAADACABAAAEADACAAAFACADAAAAAwAgAQAABAAwAgAABQAgDgMAAKIFACAIAACjBQAgEAAApAUAIJcCAQAAAAGYAgEAAAABpwJAAAAAAcACQAAAAAHtAgEAAAAB7gIBAAAAAe8CAQAAAAHxAgAAAPECAvICAQAAAAHzAgEAAAAB9AIBAAAAAQEhAACPAQAgC5cCAQAAAAGYAgEAAAABpwJAAAAAAcACQAAAAAHtAgEAAAAB7gIBAAAAAe8CAQAAAAHxAgAAAPECAvICAQAAAAHzAgEAAAAB9AIBAAAAAQEhAACRAQAwASEAAJEBADABAAAABwAgAQAAAAkAIA4DAACTBQAgCAAAlAUAIBAAAJUFACCXAgEArAQAIZgCAQCwBAAhpwJAALEEACHAAkAAsQQAIe0CAQCsBAAh7gIBAKwEACHvAgEArAQAIfECAACSBfECIvICAQCsBAAh8wIBAKwEACH0AgEAsAQAIQIAAAAFACAhAACWAQAgC5cCAQCsBAAhmAIBALAEACGnAkAAsQQAIcACQACxBAAh7QIBAKwEACHuAgEArAQAIe8CAQCsBAAh8QIAAJIF8QIi8gIBAKwEACHzAgEArAQAIfQCAQCwBAAhAgAAAAMAICEAAJgBACACAAAAAwAgIQAAmAEAIAEAAAAHACABAAAACQAgAwAAAAUAICgAAI8BACApAACWAQAgAQAAAAUAIAEAAAADACAFEwAAjwUAIDAAAJEFACAxAACQBQAgmAIAAKgEACD0AgAAqAQAIA6UAgAA9QMAMJUCAAChAQAQlgIAAPUDADCXAgEApwMAIZgCAQCoAwAhpwJAAKwDACHAAkAArAMAIe0CAQCnAwAh7gIBAKcDACHvAgEApwMAIfECAAD2A_ECIvICAQCnAwAh8wIBAKcDACH0AgEAqAMAIQMAAAADACABAACgAQAwLQAAoQEAIAMAAAADACABAAAEADACAAAFACABAAAAFgAgAQAAABYAIAMAAAAUACABAAAVADACAAAWACADAAAAFAAgAQAAFQAwAgAAFgAgAwAAABQAIAEAABUAMAIAABYAIBMIAACMBQAgCwAAigUAIAwAAIsFACAOAACNBQAgDwAAjgUAIJcCAQAAAAGYAgEAAAABoAIAAADrAgKnAkAAAAABwAJAAAAAAcgCAQAAAAHZAggAAAAB5AIBAAAAAeUCAQAAAAHnAgAAAOcCAugCCAAAAAHpAoAAAAAB6wIBAAAAAewCAQAAAAEBIQAAqQEAIA6XAgEAAAABmAIBAAAAAaACAAAA6wICpwJAAAAAAcACQAAAAAHIAgEAAAAB2QIIAAAAAeQCAQAAAAHlAgEAAAAB5wIAAADnAgLoAggAAAAB6QKAAAAAAesCAQAAAAHsAgEAAAABASEAAKsBADABIQAAqwEAMAEAAAADACABAAAACQAgEwgAAP0EACALAAD7BAAgDAAA_AQAIA4AAP4EACAPAAD_BAAglwIBAKwEACGYAgEAsAQAIaACAAD6BOsCIqcCQACxBAAhwAJAALEEACHIAgEAsAQAIdkCCADpBAAh5AIBAKwEACHlAgEAsAQAIecCAAD5BOcCIugCCADpBAAh6QKAAAAAAesCAQCsBAAh7AIBALAEACECAAAAFgAgIQAAsAEAIA6XAgEArAQAIZgCAQCwBAAhoAIAAPoE6wIipwJAALEEACHAAkAAsQQAIcgCAQCwBAAh2QIIAOkEACHkAgEArAQAIeUCAQCwBAAh5wIAAPkE5wIi6AIIAOkEACHpAoAAAAAB6wIBAKwEACHsAgEAsAQAIQIAAAAUACAhAACyAQAgAgAAABQAICEAALIBACABAAAAAwAgAQAAAAkAIAMAAAAWACAoAACpAQAgKQAAsAEAIAEAAAAWACABAAAAFAAgCRMAAPQEACAuAAD1BAAgLwAA-AQAIDAAAPcEACAxAAD2BAAgmAIAAKgEACDIAgAAqAQAIOUCAACoBAAg7AIAAKgEACARlAIAAO4DADCVAgAAuwEAEJYCAADuAwAwlwIBAKcDACGYAgEAqAMAIaACAADwA-sCIqcCQACsAwAhwAJAAKwDACHIAgEAqAMAIdkCCADkAwAh5AIBAKcDACHlAgEAqAMAIecCAADvA-cCIugCCADkAwAh6QIAAOMDACDrAgEApwMAIewCAQCoAwAhAwAAABQAIAEAALoBADAtAAC7AQAgAwAAABQAIAEAABUAMAIAABYAIA0NAADrAwAglAIAAO0DADCVAgAAGgAQlgIAAO0DADCXAgEAAAABpwJAANIDACHAAkAA0gMAIcgCAQDQAwAh1AIBAAAAAeACAQDQAwAh4QICAOkDACHiAgEA0AMAIeMCAQDQAwAhAQAAAL4BACABAAAAvgEAIAENAADsBAAgAwAAABoAIAEAAMEBADACAAC-AQAgAwAAABoAIAEAAMEBADACAAC-AQAgAwAAABoAIAEAAMEBADACAAC-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JcCAQAAAAGnAkAA0gMAIbMCAQAAAAHAAkAA0gMAIcoCIADTAwAhywIgANMDACHMAiAA0wMAIQEAAACcAgAgAQAAAJwCACABBgAAyAQAIAMAAAAxACABAACfAgAwAgAAnAIAIAMAAAAxACABAACfAgAwAgAAnAIAIAMAAAAxACABAACfAgAwAgAAnAIAIAgGAADYBAAglwIBAAAAAacCQAAAAAGzAgEAAAABwAJAAAAAAcoCIAAAAAHLAiAAAAABzAIgAAAAAQEhAACjAgAgB5cCAQAAAAGnAkAAAAABswIBAAAAAcACQAAAAAHKAiAAAAABywIgAAAAAcwCIAAAAAEBIQAApQIAMAEhAAClAgAwCAYAANcEACCXAgEArAQAIacCQACxBAAhswIBAKwEACHAAkAAsQQAIcoCIADFBAAhywIgAMUEACHMAiAAxQQAIQIAAACcAgAgIQAAqAIAIAeXAgEArAQAIacCQACxBAAhswIBAKwEACHAAkAAsQQAIcoCIADFBAAhywIgAMUEACHMAiAAxQQAIQIAAAAxACAhAACqAgAgAgAAADEAICEAAKoCACADAAAAnAIAICgAAKMCACApAACoAgAgAQAAAJwCACABAAAAMQAgAxMAANQEACAwAADWBAAgMQAA1QQAIAqUAgAA2gMAMJUCAACxAgAQlgIAANoDADCXAgEApwMAIacCQACsAwAhswIBAKcDACHAAkAArAMAIcoCIADKAwAhywIgAMoDACHMAiAAygMAIQMAAAAxACABAACwAgAwLQAAsQIAIAMAAAAxACABAACfAgAwAgAAnAIAIAEAAAARACABAAAAEQAgAwAAAA8AIAEAABAAMAIAABEAIAMAAAAPACABAAAQADACAAARACADAAAADwAgAQAAEAAwAgAAEQAgCAgAANMEACCXAgEAAAABpwJAAAAAAcACQAAAAAHEAkAAAAABxwIBAAAAAcgCAQAAAAHJAgEAAAABASEAALkCACAHlwIBAAAAAacCQAAAAAHAAkAAAAABxAJAAAAAAccCAQAAAAHIAgEAAAAByQIBAAAAAQEhAAC7AgAwASEAALsCADAICAAA0gQAIJcCAQCsBAAhpwJAALEEACHAAkAAsQQAIcQCQADRBAAhxwIBAKwEACHIAgEArAQAIckCAQCsBAAhAgAAABEAICEAAL4CACAHlwIBAKwEACGnAkAAsQQAIcACQACxBAAhxAJAANEEACHHAgEArAQAIcgCAQCsBAAhyQIBAKwEACECAAAADwAgIQAAwAIAIAIAAAAPACAhAADAAgAgAwAAABEAICgAALkCACApAAC-AgAgAQAAABEAIAEAAAAPACAEEwAAzgQAIDAAANAEACAxAADPBAAgxAIAAKgEACAKlAIAANYDADCVAgAAxwIAEJYCAADWAwAwlwIBAKcDACGnAkAArAMAIcACQACsAwAhxAJAANcDACHHAgEApwMAIcgCAQCnAwAhyQIBAKcDACEDAAAADwAgAQAAxgIAMC0AAMcCACADAAAADwAgAQAAEAAwAgAAEQAgAQAAADUAIAEAAAA1ACADAAAAMwAgAQAANAAwAgAANQAgAwAAADMAIAEAADQAMAIAADUAIAMAAAAzACABAAA0ADACAAA1ACALBgAAzQQAIJcCAQAAAAGnAkAAAAABswIBAAAAAcACQAAAAAHBAgEAAAABwgIBAAAAAcMCAQAAAAHEAkAAAAABxQJAAAAAAcYCIAAAAAEBIQAAzwIAIAqXAgEAAAABpwJAAAAAAbMCAQAAAAHAAkAAAAABwQIBAAAAAcICAQAAAAHDAgEAAAABxAJAAAAAAcUCQAAAAAHGAiAAAAABASEAANECADABIQAA0QIAMAsGAADMBAAglwIBAKwEACGnAkAAsQQAIbMCAQCsBAAhwAJAALEEACHBAgEArAQAIcICAQCwBAAhwwIBALAEACHEAkAAsQQAIcUCQACxBAAhxgIgAMUEACECAAAANQAgIQAA1AIAIAqXAgEArAQAIacCQACxBAAhswIBAKwEACHAAkAAsQQAIcECAQCsBAAhwgIBALAEACHDAgEAsAQAIcQCQACxBAAhxQJAALEEACHGAiAAxQQAIQIAAAAzACAhAADWAgAgAgAAADMAICEAANYCACADAAAANQAgKAAAzwIAICkAANQCACABAAAANQAgAQAAADMAIAUTAADJBAAgMAAAywQAIDEAAMoEACDCAgAAqAQAIMMCAACoBAAgDZQCAADVAwAwlQIAAN0CABCWAgAA1QMAMJcCAQCnAwAhpwJAAKwDACGzAgEApwMAIcACQACsAwAhwQIBAKcDACHCAgEAqAMAIcMCAQCoAwAhxAJAAKwDACHFAkAArAMAIcYCIADKAwAhAwAAADMAIAEAANwCADAtAADdAgAgAwAAADMAIAEAADQAMAIAADUAIA0GAADUAwAglAIAAM8DADCVAgAAOQAQlgIAAM8DADCXAgEAAAABoAIAANEDvgIipwJAANIDACGzAgEAAAABuwIBANADACG8AgEA0AMAIb4CQADSAwAhvwIgANMDACHAAkAA0gMAIQEAAADgAgAgAQAAAOACACABBgAAyAQAIAMAAAA5ACABAADjAgAwAgAA4AIAIAMAAAA5ACABAADjAgAwAgAA4AIAIAMAAAA5ACABAADjAgAwAgAA4AIAIAoGAADHBAAglwIBAAAAAaACAAAAvgICpwJAAAAAAbMCAQAAAAG7AgEAAAABvAIBAAAAAb4CQAAAAAG_AiAAAAABwAJAAAAAAQEhAADnAgAgCZcCAQAAAAGgAgAAAL4CAqcCQAAAAAGzAgEAAAABuwIBAAAAAbwCAQAAAAG-AkAAAAABvwIgAAAAAcACQAAAAAEBIQAA6QIAMAEhAADpAgAwCgYAAMYEACCXAgEArAQAIaACAADEBL4CIqcCQACxBAAhswIBAKwEACG7AgEArAQAIbwCAQCsBAAhvgJAALEEACG_AiAAxQQAIcACQACxBAAhAgAAAOACACAhAADsAgAgCZcCAQCsBAAhoAIAAMQEvgIipwJAALEEACGzAgEArAQAIbsCAQCsBAAhvAIBAKwEACG-AkAAsQQAIb8CIADFBAAhwAJAALEEACECAAAAOQAgIQAA7gIAIAIAAAA5ACAhAADuAgAgAwAAAOACACAoAADnAgAgKQAA7AIAIAEAAADgAgAgAQAAADkAIAMTAADBBAAgMAAAwwQAIDEAAMIEACAMlAIAAMgDADCVAgAA9QIAEJYCAADIAwAwlwIBAKcDACGgAgAAyQO-AiKnAkAArAMAIbMCAQCnAwAhuwIBAKcDACG8AgEApwMAIb4CQACsAwAhvwIgAMoDACHAAkAArAMAIQMAAAA5ACABAAD0AgAwLQAA9QIAIAMAAAA5ACABAADjAgAwAgAA4AIAIAEAAAA9ACABAAAAPQAgAwAAADsAIAEAADwAMAIAAD0AIAMAAAA7ACABAAA8ADACAAA9ACADAAAAOwAgAQAAPAAwAgAAPQAgCQYAAMAEACCXAgEAAAABoAIAAAC2AgKnAkAAAAABswIBAAAAAbQCAgAAAAG2AgEAAAABuAIAAAC4AgK6AgAAALoCAgEhAAD9AgAgCJcCAQAAAAGgAgAAALYCAqcCQAAAAAGzAgEAAAABtAICAAAAAbYCAQAAAAG4AgAAALgCAroCAAAAugICASEAAP8CADABIQAA_wIAMAkGAAC_BAAglwIBAKwEACGgAgAAvAS2AiKnAkAAsQQAIbMCAQCsBAAhtAICALsEACG2AgEArAQAIbgCAAC9BLgCIroCAAC-BLoCIgIAAAA9ACAhAACCAwAgCJcCAQCsBAAhoAIAALwEtgIipwJAALEEACGzAgEArAQAIbQCAgC7BAAhtgIBAKwEACG4AgAAvQS4AiK6AgAAvgS6AiICAAAAOwAgIQAAhAMAIAIAAAA7ACAhAACEAwAgAwAAAD0AICgAAP0CACApAACCAwAgAQAAAD0AIAEAAAA7ACAFEwAAtgQAIC4AALcEACAvAAC6BAAgMAAAuQQAIDEAALgEACALlAIAALsDADCVAgAAiwMAEJYCAAC7AwAwlwIBAKcDACGgAgAAvQO2AiKnAkAArAMAIbMCAQCnAwAhtAICALwDACG2AgEApwMAIbgCAAC-A7gCIroCAAC_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-A7gCIroCAAC_A7oCIg0TAACuAwAgLgAAxwMAIC8AAK4DACAwAACuAwAgMQAArgMAIKgCAgAAAAGpAgIAAAAEqgICAAAABKsCAgAAAAGsAgIAAAABrQICAAAAAa4CAgAAAAGvAgIAxgMAIQcTAACuAwAgMAAAxQMAIDEAAMUDACCoAgAAALYCAqkCAAAAtgIIqgIAAAC2AgivAgAAxAO2AiIHEwAArgMAIDAAAMMDACAxAADDAwAgqAIAAAC4AgKpAgAAALgCCKoCAAAAuAIIrwIAAMIDuAIiBxMAAK4DACAwAADBAwAgMQAAwQMAIKgCAAAAugICqQIAAAC6AgiqAgAAALoCCK8CAADAA7oCIgcTAACuAwAgMAAAwQMAIDEAAMEDACCoAgAAALoCAqkCAAAAugIIqgIAAAC6AgivAgAAwAO6AiIEqAIAAAC6AgKpAgAAALoCCKoCAAAAugIIrwIAAMEDugIiBxMAAK4DACAwAADDAwAgMQAAwwMAIKgCAAAAuAICqQIAAAC4AgiqAgAAALgCCK8CAADCA7gCIgSoAgAAALgCAqkCAAAAuAIIqgIAAAC4AgivAgAAwwO4AiIHEwAArgMAIDAAAMUDACAxAADFAwAgqAIAAAC2AgKpAgAAALYCCKoCAAAAtgIIrwIAAMQDtgIiBKgCAAAAtgICqQIAAAC2AgiqAgAAALYCCK8CAADFA7YCIg0TAACuAwAgLgAAxwMAIC8AAK4DACAwAACuAwAgMQAArgMAIKgCAgAAAAGpAgIAAAAEqgICAAAABKsCAgAAAAGsAgIAAAABrQICAAAAAa4CAgAAAAGvAgIAxgMAIQioAggAAAABqQIIAAAABKoCCAAAAASrAggAAAABrAIIAAAAAa0CCAAAAAGuAggAAAABrwIIAMcDACEMlAIAAMgDADCVAgAA9QIAEJYCAADIAwAwlwIBAKcDACGgAgAAyQO-AiKnAkAArAMAIbMCAQCnAwAhuwIBAKcDACG8AgEApwMAIb4CQACsAwAhvwIgAMoDACHAAkAArAMAIQcTAACuAwAgMAAAzgMAIDEAAM4DACCoAgAAAL4CAqkCAAAAvgIIqgIAAAC-AgivAgAAzQO-AiIFEwAArgMAIDAAAMwDACAxAADMAwAgqAIgAAAAAa8CIADLAwAhBRMAAK4DACAwAADMAwAgMQAAzAMAIKgCIAAAAAGvAiAAywMAIQKoAiAAAAABrwIgAMwDACEHEwAArgMAIDAAAM4DACAxAADOAwAgqAIAAAC-AgKpAgAAAL4CCKoCAAAAvgIIrwIAAM0DvgIiBKgCAAAAvgICqQIAAAC-AgiqAgAAAL4CCK8CAADOA74CIg0GAADUAwAglAIAAM8DADCVAgAAOQAQlgIAAM8DADCXAgEA0AMAIaACAADRA74CIqcCQADSAwAhswIBANADACG7AgEA0AMAIbwCAQDQAwAhvgJAANIDACG_AiAA0wMAIcACQADSAwAhC6gCAQAAAAGpAgEAAAAEqgIBAAAABKsCAQAAAAGsAgEAAAABrQIBAAAAAa4CAQAAAAGvAgEAugMAIbACAQAAAAGxAgEAAAABsgIBAAAAAQSoAgAAAL4CAqkCAAAAvgIIqgIAAAC-AgivAgAAzgO-AiIIqAJAAAAAAakCQAAAAASqAkAAAAAEqwJAAAAAAawCQAAAAAGtAkAAAAABrgJAAAAAAa8CQACvAwAhAqgCIAAAAAGvAiAAzAMAISEKAAD-AwAgEAAA_wMAIBIAAIAEACAUAACfBAAgFQAAoAQAIBYAAKEEACAXAACiBAAgGAAAlwQAIBkAAKMEACAaAACkBAAgGwAApQQAIJQCAACdBAAwlQIAAAcAEJYCAACdBAAwlwIBANADACGnAkAA0gMAIbgCAACHBLgCIsACQADSAwAh8gIBANADACH6AgEA0AMAIfsCAQCKBAAh_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_ECIvICAQCnAwAh8wIBAKcDACH0AgEAqAMAIQcTAACuAwAgMAAA-AMAIDEAAPgDACCoAgAAAPECAqkCAAAA8QIIqgIAAADxAgivAgAA9wPxAiIHEwAArgMAIDAAAPgDACAxAAD4AwAgqAIAAADxAgKpAgAAAPECCKoCAAAA8QIIrwIAAPcD8QIiBKgCAAAA8QICqQIAAADxAgiqAgAAAPECCK8CAAD4A_ECIgmUAgAA-QMAMJUCAACHAQAQlgIAAPkDADCXAgEApwMAIZgCAQCnAwAhpwJAAKwDACGzAgEApwMAIcACQACsAwAh9QIgAMoDACEIlAIAAPoDADCVAgAAcQAQlgIAAPoDADCXAgEApwMAIacCQACsAwAhwAJAAKwDACHIAgEApwMAIfYCAQCnAwAhDgQAANQDACAHAAD8AwAgCQAA_QMAIAoAAP4DACAQAAD_AwAgEgAAgAQAIJQCAAD7AwAwlQIAAAkAEJYCAAD7AwAwlwIBANADACGnAkAA0gMAIcACQADSAwAhyAIBANADACH2AgEA0AMAIQP3AgAACwAg-AIAAAsAIPkCAAALACAD9wIAAA8AIPgCAAAPACD5AgAADwAgA_cCAAADACD4AgAAAwAg-QIAAAMAIAP3AgAAFAAg-AIAABQAIPkCAAAUACAD9wIAAB4AIPgCAAAeACD5AgAAHgAgFJQCAACBBAAwlQIAAFkAEJYCAACBBAAwlwIBAKcDACGnAkAArAMAIbgCAAC-A7gCIsACQACsAwAh8gIBAKcDACH6AgEApwMAIfsCAQCoAwAh_AIBAKgDACH9AgEAqAMAIf8CAACCBP8CIoADIADKAwAhgQMCALwDACGCAwIAvAMAIYMDAQCoAwAhhAMgAMoDACGFAwEAqAMAIYYDQADXAwAhBxMAAK4DACAwAACEBAAgMQAAhAQAIKgCAAAA_wICqQIAAAD_AgiqAgAAAP8CCK8CAACDBP8CIgcTAACuAwAgMAAAhAQAIDEAAIQEACCoAgAAAP8CAqkCAAAA_wIIqgIAAAD_AgivAgAAgwT_AiIEqAIAAAD_AgKpAgAAAP8CCKoCAAAA_wIIrwIAAIQE_wIiDAYAANQDACCUAgAAhQQAMJUCAAA7ABCWAgAAhQQAMJcCAQDQAwAhoAIAAIYEtgIipwJAANIDACGzAgEA0AMAIbQCAgDpAwAhtgIBANADACG4AgAAhwS4AiK6AgAAiAS6AiIEqAIAAAC2AgKpAgAAALYCCKoCAAAAtgIIrwIAAMUDtgIiBKgCAAAAuAICqQIAAAC4AgiqAgAAALgCCK8CAADDA7gCIgSoAgAAALoCAqkCAAAAugIIqgIAAAC6AgivAgAAwQO6AiIOBgAA1AMAIJQCAACJBAAwlQIAADMAEJYCAACJBAAwlwIBANADACGnAkAA0gMAIbMCAQDQAwAhwAJAANIDACHBAgEA0AMAIcICAQCKBAAhwwIBAIoEACHEAkAA0gMAIcUCQADSAwAhxgIgANMDACELqAIBAAAAAakCAQAAAAWqAgEAAAAFqwIBAAAAAawCAQAAAAGtAgEAAAABrgIBAAAAAa8CAQC4AwAhsAIBAAAAAbECAQAAAAGyAgEAAAABDQYAANQDACCUAgAAiwQAMJUCAAArABCWAgAAiwQAMJcCAQDQAwAhpwJAANIDACGzAgEA0AMAIcACQADSAwAhzQIBANADACHOAgEA0AMAIc8CAQCKBAAh0QIAAIwE0QIi0gIgANMDACEEqAIAAADRAgKpAgAAANECCKoCAAAA0QIIrwIAAOED0QIiEwgAAJEEACARAACSBAAglAIAAI0EADCVAgAAHgAQlgIAAI0EADCXAgEA0AMAIZgCAQDQAwAhmQIBAIoEACGaAgEA0AMAIZsCAQDQAwAhnAIBANADACGeAgAAjgSeAiKgAgAAjwSgAiKiAgAAkASiAiKjAgEA0AMAIaQCAQCKBAAhpQIBAIoEACGmAgEAigQAIacCQADSAwAhBKgCAAAAngICqQIAAACeAgiqAgAAAJ4CCK8CAAC1A54CIgSoAgAAAKACAqkCAAAAoAIIqgIAAACgAgivAgAAswOgAiIEqAIAAACiAgKpAgAAAKICCKoCAAAAogIIrwIAALEDogIiEAQAANQDACAHAAD8AwAgCQAA_QMAIAoAAP4DACAQAAD_AwAgEgAAgAQAIJQCAAD7AwAwlQIAAAkAEJYCAAD7AwAwlwIBANADACGnAkAA0gMAIcACQADSAwAhyAIBANADACH2AgEA0AMAIYcDAAAJACCIAwAACQAgIQoAAP4DACAQAAD_AwAgEgAAgAQAIBQAAJ8EACAVAACgBAAgFgAAoQQAIBcAAKIEACAYAACXBAAgGQAAowQAIBoAAKQEACAbAAClBAAglAIAAJ0EADCVAgAABwAQlgIAAJ0EADCXAgEA0AMAIacCQADSAwAhuAIAAIcEuAIiwAJAANIDACHyAgEA0AMAIfoCAQDQAwAh-wIBAIoEACH8AgEAigQAIf0CAQCKBAAh_wIAAJ4E_wIigAMgANMDACGBAwIA6QMAIYIDAgDpAwAhgwMBAIoEACGEAyAA0wMAIYUDAQCKBAAhhgNAAJsEACGHAwAABwAgiAMAAAcAIBYIAACXBAAgCwAA1AMAIAwAAJYEACAOAACYBAAgDwAAmQQAIJQCAACTBAAwlQIAABQAEJYCAACTBAAwlwIBANADACGYAgEAigQAIaACAACVBOsCIqcCQADSAwAhwAJAANIDACHIAgEAigQAIdkCCADqAwAh5AIBANADACHlAgEAigQAIecCAACUBOcCIugCCADqAwAh6QIAAOgDACDrAgEA0AMAIewCAQCKBAAhBKgCAAAA5wICqQIAAADnAgiqAgAAAOcCCK8CAAD0A-cCIgSoAgAAAOsCAqkCAAAA6wIIqgIAAADrAgivAgAA8gPrAiITAwAAkgQAIAgAAJcEACAQAAD_AwAglAIAAKYEADCVAgAAAwAQlgIAAKYEADCXAgEA0AMAIZgCAQCKBAAhpwJAANIDACHAAkAA0gMAIe0CAQDQAwAh7gIBANADACHvAgEA0AMAIfECAACnBPECIvICAQDQAwAh8wIBANADACH0AgEAigQAIYcDAAADACCIAwAAAwAgEAQAANQDACAHAAD8AwAgCQAA_QMAIAoAAP4DACAQAAD_AwAgEgAAgAQAIJQCAAD7AwAwlQIAAAkAEJYCAAD7AwAwlwIBANADACGnAkAA0gMAIcACQADSAwAhyAIBANADACH2AgEA0AMAIYcDAAAJACCIAwAACQAgDw0AAOsDACCUAgAA7QMAMJUCAAAaABCWAgAA7QMAMJcCAQDQAwAhpwJAANIDACHAAkAA0gMAIcgCAQDQAwAh1AIBANADACHgAgEA0AMAIeECAgDpAwAh4gIBANADACHjAgEA0AMAIYcDAAAaACCIAwAAGgAgEA0AAOsDACCUAgAA5wMAMJUCAAAcABCWAgAA5wMAMJcCAQDQAwAhpwJAANIDACHAAkAA0gMAIdMCAADoAwAg1AIBANADACHVAgEA0AMAIdYCIADTAwAh1wICAOkDACHYAgEAigQAIdkCCADqAwAhhwMAABwAIIgDAAAcACALCAAAkQQAIJQCAACaBAAwlQIAAA8AEJYCAACaBAAwlwIBANADACGnAkAA0gMAIcACQADSAwAhxAJAAJsEACHHAgEA0AMAIcgCAQDQAwAhyQIBANADACEIqAJAAAAAAakCQAAAAAWqAkAAAAAFqwJAAAAAAawCQAAAAAGtAkAAAAABrgJAAAAAAa8CQADZAwAhCwUAAJEEACAGAADUAwAglAIAAJwEADCVAgAACwAQlgIAAJwEADCXAgEA0AMAIZgCAQDQAwAhpwJAANIDACGzAgEA0AMAIcACQADSAwAh9QIgANMDACEfCgAA_gMAIBAAAP8DACASAACABAAgFAAAnwQAIBUAAKAEACAWAAChBAAgFwAAogQAIBgAAJcEACAZAACjBAAgGgAApAQAIBsAAKUEACCUAgAAnQQAMJUCAAAHABCWAgAAnQQAMJcCAQDQAwAhpwJAANIDACG4AgAAhwS4AiLAAkAA0gMAIfICAQDQAwAh-gIBANADACH7AgEAigQAIfwCAQCKBAAh_QIBAIoEACH_AgAAngT_AiKAAyAA0wMAIYEDAgDpAwAhggMCAOkDACGDAwEAigQAIYQDIADTAwAhhQMBAIoEACGGA0AAmwQAIQSoAgAAAP8CAqkCAAAA_wIIqgIAAAD_AgivAgAAhAT_AiID9wIAACsAIPgCAAArACD5AgAAKwAgDQYAANQDACCUAgAA3QMAMJUCAAAvABCWAgAA3QMAMJcCAQDQAwAhpwJAANIDACGzAgEA0AMAIcACQADSAwAhygIgANMDACHLAiAA0wMAIcwCIADTAwAhhwMAAC8AIIgDAAAvACANBgAA1AMAIJQCAADbAwAwlQIAADEAEJYCAADbAwAwlwIBANADACGnAkAA0gMAIbMCAQDQAwAhwAJAANIDACHKAiAA0wMAIcsCIADTAwAhzAIgANMDACGHAwAAMQAgiAMAADEAIAP3AgAAMwAg-AIAADMAIPkCAAAzACANBQAAkQQAIAYAANQDACCUAgAAnAQAMJUCAAALABCWAgAAnAQAMJcCAQDQAwAhmAIBANADACGnAkAA0gMAIbMCAQDQAwAhwAJAANIDACH1AiAA0wMAIYcDAAALACCIAwAACwAgDwYAANQDACCUAgAAzwMAMJUCAAA5ABCWAgAAzwMAMJcCAQDQAwAhoAIAANEDvgIipwJAANIDACGzAgEA0AMAIbsCAQDQAwAhvAIBANADACG-AkAA0gMAIb8CIADTAwAhwAJAANIDACGHAwAAOQAgiAMAADkAIAP3AgAAOwAg-AIAADsAIPkCAAA7ACARAwAAkgQAIAgAAJcEACAQAAD_AwAglAIAAKYEADCVAgAAAwAQlgIAAKYEADCXAgEA0AMAIZgCAQCKBAAhpwJAANIDACHAAkAA0gMAIe0CAQDQAwAh7gIBANADACHvAgEA0AMAIfECAACnBPECIvICAQDQAwAh8wIBANADACH0AgEAigQAIQSoAgAAAPECAqkCAAAA8QIIqgIAAADxAgivAgAA-APxAiIAAAAAAY8DAQAAAAEBjwMAAACeAgIBjwMAAACgAgIBjwMAAACiAgIBjwMBAAAAAQGPA0AAAAABBSgAANsHACApAADhBwAgiQMAANwHACCKAwAA4AcAII0DAABcACAHKAAA2QcAICkAAN4HACCJAwAA2gcAIIoDAADdBwAgiwMAAAcAIIwDAAAHACCNAwAAAQAgAygAANsHACCJAwAA3AcAII0DAABcACADKAAA2QcAIIkDAADaBwAgjQMAAAEAIAAAAAAABY8DAgAAAAGSAwIAAAABkwMCAAAAAZQDAgAAAAGVAwIAAAABAY8DAAAAtgICAY8DAAAAuAICAY8DAAAAugICBSgAANQHACApAADXBwAgiQMAANUHACCKAwAA1gcAII0DAAABACADKAAA1AcAIIkDAADVBwAgjQMAAAEAIAAAAAGPAwAAAL4CAgGPAyAAAAABBSgAAM8HACApAADSBwAgiQMAANAHACCKAwAA0QcAII0DAAABACADKAAAzwcAIIkDAADQBwAgjQMAAAEAIBEKAAD2BQAgEAAA9wUAIBIAAPgFACAUAADtBgAgFQAA7gYAIBYAAO8GACAXAADwBgAgGAAA8QYAIBkAAPIGACAaAADzBgAgGwAA9AYAIPsCAACoBAAg_AIAAKgEACD9AgAAqAQAIIMDAACoBAAghQMAAKgEACCGAwAAqAQAIAAAAAUoAADKBwAgKQAAzQcAIIkDAADLBwAgigMAAMwHACCNAwAAAQAgAygAAMoHACCJAwAAywcAII0DAAABACAAAAABjwNAAAAAAQUoAADFBwAgKQAAyAcAIIkDAADGBwAgigMAAMcHACCNAwAAXAAgAygAAMUHACCJAwAAxgcAII0DAABcACAAAAAFKAAAwAcAICkAAMMHACCJAwAAwQcAIIoDAADCBwAgjQMAAAEAIAMoAADABwAgiQMAAMEHACCNAwAAAQAgAAAABSgAALsHACApAAC-BwAgiQMAALwHACCKAwAAvQcAII0DAAABACADKAAAuwcAIIkDAAC8BwAgjQMAAAEAIAAAAAGPAwAAANECAgUoAAC2BwAgKQAAuQcAIIkDAAC3BwAgigMAALgHACCNAwAAAQAgAygAALYHACCJAwAAtwcAII0DAAABACAAAAAAAAWPAwgAAAABkgMIAAAAAZMDCAAAAAGUAwgAAAABlQMIAAAAAQUoAACxBwAgKQAAtAcAIIkDAACyBwAgigMAALMHACCNAwAAFgAgAygAALEHACCJAwAAsgcAII0DAAAWACAJCAAA8QYAIAsAAMgEACAMAAD1BgAgDgAA9gYAIA8AAPcGACCYAgAAqAQAIMgCAACoBAAg5QIAAKgEACDsAgAAqAQAIAAAAAAABSgAAKwHACApAACvBwAgiQMAAK0HACCKAwAArgcAII0DAAAWACADKAAArAcAIIkDAACtBwAgjQMAABYAIAAAAAAAAY8DAAAA5wICAY8DAAAA6wICBSgAAKEHACApAACqBwAgiQMAAKIHACCKAwAAqQcAII0DAAABACAHKAAAnwcAICkAAKcHACCJAwAAoAcAIIoDAACmBwAgiwMAAAMAIIwDAAADACCNAwAABQAgBygAAJ0HACApAACkBwAgiQMAAJ4HACCKAwAAowcAIIsDAAAJACCMAwAACQAgjQMAAFwAIAcoAACFBQAgKQAAiAUAIIkDAACGBQAgigMAAIcFACCLAwAAGgAgjAMAABoAII0DAAC-AQAgBygAAIAFACApAACDBQAgiQMAAIEFACCKAwAAggUAIIsDAAAcACCMAwAAHAAgjQMAANYBACAJlwIBAAAAAacCQAAAAAHAAkAAAAAB0wKAAAAAAdUCAQAAAAHWAiAAAAAB1wICAAAAAdgCAQAAAAHZAggAAAABAgAAANYBACAoAACABQAgAwAAABwAICgAAIAFACApAACEBQAgCwAAABwAICEAAIQFACCXAgEArAQAIacCQACxBAAhwAJAALEEACHTAoAAAAAB1QIBAKwEACHWAiAAxQQAIdcCAgC7BAAh2AIBALAEACHZAggA6QQAIQmXAgEArAQAIacCQACxBAAhwAJAALEEACHTAoAAAAAB1QIBAKwEACHWAiAAxQQAIdcCAgC7BAAh2AIBALAEACHZAggA6QQAIQiXAgEAAAABpwJAAAAAAcACQAAAAAHIAgEAAAAB4AIBAAAAAeECAgAAAAHiAgEAAAAB4wIBAAAAAQIAAAC-AQAgKAAAhQUAIAMAAAAaACAoAACFBQAgKQAAiQUAIAoAAAAaACAhAACJBQAglwIBAKwEACGnAkAAsQQAIcACQACxBAAhyAIBAKwEACHgAgEArAQAIeECAgC7BAAh4gIBAKwEACHjAgEArAQAIQiXAgEArAQAIacCQACxBAAhwAJAALEEACHIAgEArAQAIeACAQCsBAAh4QICALsEACHiAgEArAQAIeMCAQCsBAAhAygAAKEHACCJAwAAogcAII0DAAABACADKAAAnwcAIIkDAACgBwAgjQMAAAUAIAMoAACdBwAgiQMAAJ4HACCNAwAAXAAgAygAAIUFACCJAwAAhgUAII0DAAC-AQAgAygAAIAFACCJAwAAgQUAII0DAADWAQAgAAAAAY8DAAAA8QICBygAAJQHACApAACbBwAgiQMAAJUHACCKAwAAmgcAIIsDAAAHACCMAwAABwAgjQMAAAEAIAcoAACSBwAgKQAAmAcAIIkDAACTBwAgigMAAJcHACCLAwAACQAgjAMAAAkAII0DAABcACALKAAAlgUAMCkAAJsFADCJAwAAlwUAMIoDAACYBQAwiwMAAJoFADCMAwAAmgUAMI0DAACaBQAwjgMAAJkFACCPAwAAmgUAMJADAACcBQAwkQMAAJ0FADARCAAAjAUAIAsAAIoFACAOAACNBQAgDwAAjgUAIJcCAQAAAAGYAgEAAAABoAIAAADrAgKnAkAAAAABwAJAAAAAAcgCAQAAAAHZAggAAAAB5AIBAAAAAeUCAQAAAAHnAgAAAOcCAugCCAAAAAHpAoAAAAAB6wIBAAAAAQIAAAAWACAoAAChBQAgAwAAABYAICgAAKEFACApAACgBQAgASEAAJYHADAWCAAAlwQAIAsAANQDACAMAACWBAAgDgAAmAQAIA8AAJkEACCUAgAAkwQAMJUCAAAUABCWAgAAkwQAMJcCAQAAAAGYAgEAigQAIaACAACVBOsCIqcCQADSAwAhwAJAANIDACHIAgEAigQAIdkCCADqAwAh5AIBAAAAAeUCAQCKBAAh5wIAAJQE5wIi6AIIAOoDACHpAgAA6AMAIOsCAQDQAwAh7AIBAIoEACECAAAAFgAgIQAAoAUAIAIAAACeBQAgIQAAnwUAIBGUAgAAnQUAMJUCAACeBQAQlgIAAJ0FADCXAgEA0AMAIZgCAQCKBAAhoAIAAJUE6wIipwJAANIDACHAAkAA0gMAIcgCAQCKBAAh2QIIAOoDACHkAgEA0AMAIeUCAQCKBAAh5wIAAJQE5wIi6AIIAOoDACHpAgAA6AMAIOsCAQDQAwAh7AIBAIoEACERlAIAAJ0FADCVAgAAngUAEJYCAACdBQAwlwIBANADACGYAgEAigQAIaACAACVBOsCIqcCQADSAwAhwAJAANIDACHIAgEAigQAIdkCCADqAwAh5AIBANADACHlAgEAigQAIecCAACUBOcCIugCCADqAwAh6QIAAOgDACDrAgEA0AMAIewCAQCKBAAhDZcCAQCsBAAhmAIBALAEACGgAgAA-gTrAiKnAkAAsQQAIcACQACxBAAhyAIBALAEACHZAggA6QQAIeQCAQCsBAAh5QIBALAEACHnAgAA-QTnAiLoAggA6QQAIekCgAAAAAHrAgEArAQAIREIAAD9BAAgCwAA-wQAIA4AAP4EACAPAAD_BAAglwIBAKwEACGYAgEAsAQAIaACAAD6BOsCIqcCQACxBAAhwAJAALEEACHIAgEAsAQAIdkCCADpBAAh5AIBAKwEACHlAgEAsAQAIecCAAD5BOcCIugCCADpBAAh6QKAAAAAAesCAQCsBAAhEQgAAIwFACALAACKBQAgDgAAjQUAIA8AAI4FACCXAgEAAAABmAIBAAAAAaACAAAA6wICpwJAAAAAAcACQAAAAAHIAgEAAAAB2QIIAAAAAeQCAQAAAAHlAgEAAAAB5wIAAADnAgLoAggAAAAB6QKAAAAAAesCAQAAAAEDKAAAlAcAIIkDAACVBwAgjQMAAAEAIAMoAACSBwAgiQMAAJMHACCNAwAAXAAgBCgAAJYFADCJAwAAlwUAMI0DAACaBQAwjgMAAJkFACAAAAAFKAAAigcAICkAAJAHACCJAwAAiwcAIIoDAACPBwAgjQMAAFwAIAUoAACIBwAgKQAAjQcAIIkDAACJBwAgigMAAIwHACCNAwAAAQAgAygAAIoHACCJAwAAiwcAII0DAABcACADKAAAiAcAIIkDAACJBwAgjQMAAAEAIAAAAAUoAAD-BgAgKQAAhgcAIIkDAAD_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_AQAIA4AAP4EACAPAAD_BAAglwIBAKwEACGgAgAA-gTrAiKnAkAAsQQAIcACQACxBAAhyAIBALAEACHZAggA6QQAIeQCAQCsBAAh5QIBALAEACHnAgAA-QTnAiLoAggA6QQAIekCgAAAAAHrAgEArAQAIewCAQCwBAAhEQsAAIoFACAMAACLBQAgDgAAjQUAIA8AAI4FACCXAgEAAAABoAIAAADrAgKnAkAAAAABwAJAAAAAAcgCAQAAAAHZAggAAAAB5AIBAAAAAeUCAQAAAAHnAgAAAOcCAugCCAAAAAHpAoAAAAAB6wIBAAAAAewCAQAAAAEMAwAAogUAIBAAAKQFACCXAgEAAAABpwJAAAAAAcACQAAAAAHtAgEAAAAB7gIBAAAAAe8CAQAAAAHxAgAAAPECAvICAQAAAAHzAgEAAAAB9AIBAAAAAQIAAAAFACAoAADVBQAgAwAAAAUAICgAANUFACApAADUBQAgASEAAIIHADARAwAAkgQAIAgAAJcEACAQAAD_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_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_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_AIBAAAAAf0CAQAAAAH_AgAAAP8CAoADIAAAAAGBAwIAAAABggMCAAAAAYMDAQAAAAGEAyAAAAABhQMBAAAAAYYDQAAAAAECAAAAAQAgKAAA_gYAIAWXAgEAAAABpwJAAAAAAbMCAQAAAAHAAkAAAAAB9QIgAAAAAQaXAgEAAAABpwJAAAAAAcACQAAAAAHEAkAAAAAByAIBAAAAAckCAQAAAAEKlwIBAAAAAacCQAAAAAHAAkAAAAAB7QIBAAAAAe4CAQAAAAHvAgEAAAAB8QIAAADxAgLyAgEAAAAB8wIBAAAAAfQCAQAAAAENlwIBAAAAAaACAAAA6wICpwJAAAAAAcACQAAAAAHIAgEAAAAB2QIIAAAAAeQCAQAAAAHlAgEAAAAB5wIAAADnAgLoAggAAAAB6QKAAAAAAesCAQAAAAHsAgEAAAABDZcCAQAAAAGZAgEAAAABmgIBAAAAAZsCAQAAAAGcAgEAAAABngIAAACeAgKgAgAAAKACAqICAAAAogICowIBAAAAAaQCAQAAAAGlAgEAAAABpgIBAAAAAacCQAAAAAEDAAAABwAgKAAA_gYAICkAAIcHACAdAAAABwAgCgAA_wUAIBAAAIAGACASAACJBgAgFAAAgQYAIBUAAIIGACAWAACDBgAgFwAAhAYAIBkAAIYGACAaAACHBgAgGwAAiAYAICEAAIcHACCXAgEArAQAIacCQACxBAAhuAIAAL0EuAIiwAJAALEEACHyAgEArAQAIfoCAQCsBAAh-wIBALAEACH8AgEAsAQAIf0CAQCwBAAh_wIAAP4F_wIigAMgAMUEACGBAwIAuwQAIYIDAgC7BAAhgwMBALAEACGEAyAAxQQAIYUDAQCwBAAhhgNAANEEACEbCgAA_wUAIBAAAIAGACASAACJBgAgFAAAgQYAIBUAAIIGACAWAACDBgAgFwAAhAYAIBkAAIYGACAaAACHBgAgGwAAiAYAIJcCAQCsBAAhpwJAALEEACG4AgAAvQS4AiLAAkAAsQQAIfICAQCsBAAh-gIBAKwEACH7AgEAsAQAIfwCAQCwBAAh_QIBALAEACH_AgAA_gX_AiKAAyAAxQQAIYEDAgC7BAAhggMCALsEACGDAwEAsAQAIYQDIADFBAAhhQMBALAEACGGA0AA0QQAIRsKAADiBgAgEAAA4wYAIBIAAOwGACAUAADkBgAgFQAA5QYAIBYAAOYGACAXAADnBgAgGAAA6AYAIBoAAOoGACAbAADrBgAglwIBAAAAAacCQAAAAAG4AgAAALgCAsACQAAAAAHyAgEAAAAB-gIBAAAAAfsCAQAAAAH8AgEAAAAB_QIBAAAAAf8CAAAA_wICgAMgAAAAAYEDAgAAAAGCAwIAAAABgwMBAAAAAYQDIAAAAAGFAwEAAAABhgNAAAAAAQIAAAABACAoAACIBwAgCgQAAO4FACAJAADwBQAgCgAA8QUAIBAAAPIFACASAADzBQAglwIBAAAAAacCQAAAAAHAAkAAAAAByAIBAAAAAfYCAQAAAAECAAAAXAAgKAAAigcAIAMAAAAHACAoAACIBwAgKQAAjgcAIB0AAAAHACAKAAD_BQAgEAAAgAYAIBIAAIkGACAUAACBBgAgFQAAggYAIBYAAIMGACAXAACEBgAgGAAAhQYAIBoAAIcGACAbAACIBgAgIQAAjgcAIJcCAQCsBAAhpwJAALEEACG4AgAAvQS4AiLAAkAAsQQAIfICAQCsBAAh-gIBAKwEACH7AgEAsAQAIfwCAQCwBAAh_QIBALAEACH_AgAA_gX_AiKAAyAAxQQAIYEDAgC7BAAhggMCALsEACGDAwEAsAQAIYQDIADFBAAhhQMBALAEACGGA0AA0QQAIRsKAAD_BQAgEAAAgAYAIBIAAIkGACAUAACBBgAgFQAAggYAIBYAAIMGACAXAACEBgAgGAAAhQYAIBoAAIcGACAbAACIBgAglwIBAKwEACGnAkAAsQQAIbgCAAC9BLgCIsACQACxBAAh8gIBAKwEACH6AgEArAQAIfsCAQCwBAAh_AIBALAEACH9AgEAsAQAIf8CAAD-Bf8CIoADIADFBAAhgQMCALsEACGCAwIAuwQAIYMDAQCwBAAhhAMgAMUEACGFAwEAsAQAIYYDQADRBAAhAwAAAAkAICgAAIoHACApAACRBwAgDAAAAAkAIAQAAK8FACAJAACxBQAgCgAAsgUAIBAAALMFACASAAC0BQAgIQAAkQcAIJcCAQCsBAAhpwJAALEEACHAAkAAsQQAIcgCAQCsBAAh9gIBAKwEACEKBAAArwUAIAkAALEFACAKAACyBQAgEAAAswUAIBIAALQFACCXAgEArAQAIacCQACxBAAhwAJAALEEACHIAgEArAQAIfYCAQCsBAAhCgQAAO4FACAHAADvBQAgCQAA8AUAIBAAAPIFACASAADzBQAglwIBAAAAAacCQAAAAAHAAkAAAAAByAIBAAAAAfYCAQAAAAECAAAAXAAgKAAAkgcAIBsQAADjBgAgEgAA7AYAIBQAAOQGACAVAADlBgAgFgAA5gYAIBcAAOcGACAYAADoBgAgGQAA6QYAIBoAAOoGACAbAADrBgAglwIBAAAAAacCQAAAAAG4AgAAALgCAsACQAAAAAHyAgEAAAAB-gIBAAAAAfsCAQAAAAH8AgEAAAAB_QIBAAAAAf8CAAAA_wICgAMgAAAAAYEDAgAAAAGCAwIAAAABgwMBAAAAAYQDIAAAAAGFAwEAAAABhgNAAAAAAQIAAAABACAoAACUBwAgDZcCAQAAAAGYAgEAAAABoAIAAADrAgKnAkAAAAABwAJAAAAAAcgCAQAAAAHZAggAAAAB5AIBAAAAAeUCAQAAAAHnAgAAAOcCAugCCAAAAAHpAoAAAAAB6wIBAAAAAQMAAAAJACAoAACSBwAgKQAAmQcAIAwAAAAJACAEAACvBQAgBwAAsAUAIAkAALEFACAQAACzBQAgEgAAtAUAICEAAJkHACCXAgEArAQAIacCQACxBAAhwAJAALEEACHIAgEArAQAIfYCAQCsBAAhCgQAAK8FACAHAACwBQAgCQAAsQUAIBAAALMFACASAAC0BQAglwIBAKwEACGnAkAAsQQAIcACQACxBAAhyAIBAKwEACH2AgEArAQAIQMAAAAHACAoAACUBwAgKQAAnAcAIB0AAAAHACAQAACABgAgEgAAiQYAIBQAAIEGACAVAACCBgAgFgAAgwYAIBcAAIQGACAYAACFBgAgGQAAhgYAIBoAAIcGACAbAACIBgAgIQAAnAcAIJcCAQCsBAAhpwJAALEEACG4AgAAvQS4AiLAAkAAsQQAIfICAQCsBAAh-gIBAKwEACH7AgEAsAQAIfwCAQCwBAAh_QIBALAEACH_AgAA_gX_AiKAAyAAxQQAIYEDAgC7BAAhggMCALsEACGDAwEAsAQAIYQDIADFBAAhhQMBALAEACGGA0AA0QQAIRsQAACABgAgEgAAiQYAIBQAAIEGACAVAACCBgAgFgAAgwYAIBcAAIQGACAYAACFBgAgGQAAhgYAIBoAAIcGACAbAACIBgAglwIBAKwEACGnAkAAsQQAIbgCAAC9BLgCIsACQACxBAAh8gIBAKwEACH6AgEArAQAIfsCAQCwBAAh_AIBALAEACH9AgEAsAQAIf8CAAD-Bf8CIoADIADFBAAhgQMCALsEACGCAwIAuwQAIYMDAQCwBAAhhAMgAMUEACGFAwEAsAQAIYYDQADRBAAhCgQAAO4FACAHAADvBQAgCQAA8AUAIAoAAPEFACASAADzBQAglwIBAAAAAacCQAAAAAHAAkAAAAAByAIBAAAAAfYCAQAAAAECAAAAXAAgKAAAnQcAIA0DAACiBQAgCAAAowUAIJcCAQAAAAGYAgEAAAABpwJAAAAAAcACQAAAAAHtAgEAAAAB7gIBAAAAAe8CAQAAAAHxAgAAAPECAvICAQAAAAHzAgEAAAAB9AIBAAAAAQIAAAAFACAoAACfBwAgGwoAAOIGACASAADsBgAgFAAA5AYAIBUAAOUGACAWAADmBgAgFwAA5wYAIBgAAOgGACAZAADpBgAgGgAA6gYAIBsAAOsGACCXAgEAAAABpwJAAAAAAbgCAAAAuAICwAJAAAAAAfICAQAAAAH6AgEAAAAB-wIBAAAAAfwCAQAAAAH9AgEAAAAB_wIAAAD_AgKAAyAAAAABgQMCAAAAAYIDAgAAAAGDAwEAAAABhAMgAAAAAYUDAQAAAAGGA0AAAAABAgAAAAEAICgAAKEHACADAAAACQAgKAAAnQcAICkAAKUHACAMAAAACQAgBAAArwUAIAcAALAFACAJAACxBQAgCgAAsgUAIBIAALQFACAhAAClBwAglwIBAKwEACGnAkAAsQQAIcACQACxBAAhyAIBAKwEACH2AgEArAQAIQoEAACvBQAgBwAAsAUAIAkAALEFACAKAACyBQAgEgAAtAUAIJcCAQCsBAAhpwJAALEEACHAAkAAsQQAIcgCAQCsBAAh9gIBAKwEACEDAAAAAwAgKAAAnwcAICkAAKgHACAPAAAAAwAgAwAAkwUAIAgAAJQFACAhAACoBwAglwIBAKwEACGYAgEAsAQAIacCQACxBAAhwAJAALEEACHtAgEArAQAIe4CAQCsBAAh7wIBAKwEACHxAgAAkgXxAiLyAgEArAQAIfMCAQCsBAAh9AIBALAEACENAwAAkwUAIAgAAJQFACCXAgEArAQAIZgCAQCwBAAhpwJAALEEACHAAkAAsQQAIe0CAQCsBAAh7gIBAKwEACHvAgEArAQAIfECAACSBfECIvICAQCsBAAh8wIBAKwEACH0AgEAsAQAIQMAAAAHACAoAAChBwAgKQAAqwcAIB0AAAAHACAKAAD_BQAgEgAAiQYAIBQAAIEGACAVAACCBgAgFgAAgwYAIBcAAIQGACAYAACFBgAgGQAAhgYAIBoAAIcGACAbAACIBgAgIQAAqwcAIJcCAQCsBAAhpwJAALEEACG4AgAAvQS4AiLAAkAAsQQAIfICAQCsBAAh-gIBAKwEACH7AgEAsAQAIfwCAQCwBAAh_QIBALAEACH_AgAA_gX_AiKAAyAAxQQAIYEDAgC7BAAhggMCALsEACGDAwEAsAQAIYQDIADFBAAhhQMBALAEACGGA0AA0QQAIRsKAAD_BQAgEgAAiQYAIBQAAIEGACAVAACCBgAgFgAAgwYAIBcAAIQGACAYAACFBgAgGQAAhgYAIBoAAIcGACAbAACIBgAglwIBAKwEACGnAkAAsQQAIbgCAAC9BLgCIsACQACxBAAh8gIBAKwEACH6AgEArAQAIfsCAQCwBAAh_AIBALAEACH9AgEAsAQAIf8CAAD-Bf8CIoADIADFBAAhgQMCALsEACGCAwIAuwQAIYMDAQCwBAAhhAMgAMUEACGFAwEAsAQAIYYDQADRBAAhEggAAIwFACALAACKBQAgDAAAiwUAIA8AAI4FACCXAgEAAAABmAIBAAAAAaACAAAA6wICpwJAAAAAAcACQAAAAAHIAgEAAAAB2QIIAAAAAeQCAQAAAAHlAgEAAAAB5wIAAADnAgLoAggAAAAB6QKAAAAAAesCAQAAAAHsAgEAAAABAgAAABYAICgAAKwHACADAAAAFAAgKAAArAcAICkAALAHACAUAAAAFAAgCAAA_QQAIAsAAPsEACAMAAD8BAAgDwAA_wQAICEAALAHACCXAgEArAQAIZgCAQCwBAAhoAIAAPoE6wIipwJAALEEACHAAkAAsQQAIcgCAQCwBAAh2QIIAOkEACHkAgEArAQAIeUCAQCwBAAh5wIAAPkE5wIi6AIIAOkEACHpAoAAAAAB6wIBAKwEACHsAgEAsAQAIRIIAAD9BAAgCwAA-wQAIAwAAPwEACAPAAD_BAAglwIBAKwEACGYAgEAsAQAIaACAAD6BOsCIqcCQACxBAAhwAJAALEEACHIAgEAsAQAIdkCCADpBAAh5AIBAKwEACHlAgEAsAQAIecCAAD5BOcCIugCCADpBAAh6QKAAAAAAesCAQCsBAAh7AIBALAEACESCAAAjAUAIAsAAIoFACAMAACLBQAgDgAAjQUAIJcCAQAAAAGYAgEAAAABoAIAAADrAgKnAkAAAAABwAJAAAAAAcgCAQAAAAHZAggAAAAB5AIBAAAAAeUCAQAAAAHnAgAAAOcCAugCCAAAAAHpAoAAAAAB6wIBAAAAAewCAQAAAAECAAAAFgAgKAAAsQcAIAMAAAAUACAoAACxBwAgKQAAtQcAIBQAAAAUACAIAAD9BAAgCwAA-wQAIAwAAPwEACAOAAD-BAAgIQAAtQcAIJcCAQCsBAAhmAIBALAEACGgAgAA-gTrAiKnAkAAsQQAIcACQACxBAAhyAIBALAEACHZAggA6QQAIeQCAQCsBAAh5QIBALAEACHnAgAA-QTnAiLoAggA6QQAIekCgAAAAAHrAgEArAQAIewCAQCwBAAhEggAAP0EACALAAD7BAAgDAAA_AQAIA4AAP4EACCXAgEArAQAIZgCAQCwBAAhoAIAAPoE6wIipwJAALEEACHAAkAAsQQAIcgCAQCwBAAh2QIIAOkEACHkAgEArAQAIeUCAQCwBAAh5wIAAPkE5wIi6AIIAOkEACHpAoAAAAAB6wIBAKwEACHsAgEAsAQAIRsKAADiBgAgEAAA4wYAIBIAAOwGACAVAADlBgAgFgAA5gYAIBcAAOcGACAYAADoBgAgGQAA6QYAIBoAAOoGACAbAADrBgAglwIBAAAAAacCQAAAAAG4AgAAALgCAsACQAAAAAHyAgEAAAAB-gIBAAAAAfsCAQAAAAH8AgEAAAAB_QIBAAAAAf8CAAAA_wICgAMgAAAAAYEDAgAAAAGCAwIAAAABgwMBAAAAAYQDIAAAAAGFAwEAAAABhgNAAAAAAQIAAAABACAoAAC2BwAgAwAAAAcAICgAALYHACApAAC6BwAgHQAAAAcAIAoAAP8FACAQAACABgAgEgAAiQYAIBUAAIIGACAWAACDBgAgFwAAhAYAIBgAAIUGACAZAACGBgAgGgAAhwYAIBsAAIgGACAhAAC6BwAglwIBAKwEACGnAkAAsQQAIbgCAAC9BLgCIsACQACxBAAh8gIBAKwEACH6AgEArAQAIfsCAQCwBAAh_AIBALAEACH9AgEAsAQAIf8CAAD-Bf8CIoADIADFBAAhgQMCALsEACGCAwIAuwQAIYMDAQCwBAAhhAMgAMUEACGFAwEAsAQAIYYDQADRBAAhGwoAAP8FACAQAACABgAgEgAAiQYAIBUAAIIGACAWAACDBgAgFwAAhAYAIBgAAIUGACAZAACGBgAgGgAAhwYAIBsAAIgGACCXAgEArAQAIacCQACxBAAhuAIAAL0EuAIiwAJAALEEACHyAgEArAQAIfoCAQCsBAAh-wIBALAEACH8AgEAsAQAIf0CAQCwBAAh_wIAAP4F_wIigAMgAMUEACGBAwIAuwQAIYIDAgC7BAAhgwMBALAEACGEAyAAxQQAIYUDAQCwBAAhhgNAANEEACEbCgAA4gYAIBAAAOMGACASAADsBgAgFAAA5AYAIBYAAOYGACAXAADnBgAgGAAA6AYAIBkAAOkGACAaAADqBgAgGwAA6wYAIJcCAQAAAAGnAkAAAAABuAIAAAC4AgLAAkAAAAAB8gIBAAAAAfoCAQAAAAH7AgEAAAAB_AIBAAAAAf0CAQAAAAH_AgAAAP8CAoADIAAAAAGBAwIAAAABggMCAAAAAYMDAQAAAAGEAyAAAAABhQMBAAAAAYYDQAAAAAECAAAAAQAgKAAAuwcAIAMAAAAHACAoAAC7BwAgKQAAvwcAIB0AAAAHACAKAAD_BQAgEAAAgAYAIBIAAIkGACAUAACBBgAgFgAAgwYAIBcAAIQGACAYAACFBgAgGQAAhgYAIBoAAIcGACAbAACIBgAgIQAAvwcAIJcCAQCsBAAhpwJAALEEACG4AgAAvQS4AiLAAkAAsQQAIfICAQCsBAAh-gIBAKwEACH7AgEAsAQAIfwCAQCwBAAh_QIBALAEACH_AgAA_gX_AiKAAyAAxQQAIYEDAgC7BAAhggMCALsEACGDAwEAsAQAIYQDIADFBAAhhQMBALAEACGGA0AA0QQAIRsKAAD_BQAgEAAAgAYAIBIAAIkGACAUAACBBgAgFgAAgwYAIBcAAIQGACAYAACFBgAgGQAAhgYAIBoAAIcGACAbAACIBgAglwIBAKwEACGnAkAAsQQAIbgCAAC9BLgCIsACQACxBAAh8gIBAKwEACH6AgEArAQAIfsCAQCwBAAh_AIBALAEACH9AgEAsAQAIf8CAAD-Bf8CIoADIADFBAAhgQMCALsEACGCAwIAuwQAIYMDAQCwBAAhhAMgAMUEACGFAwEAsAQAIYYDQADRBAAhGwoAAOIGACAQAADjBgAgEgAA7AYAIBQAAOQGACAVAADlBgAgFwAA5wYAIBgAAOgGACAZAADpBgAgGgAA6gYAIBsAAOsGACCXAgEAAAABpwJAAAAAAbgCAAAAuAICwAJAAAAAAfICAQAAAAH6AgEAAAAB-wIBAAAAAfwCAQAAAAH9AgEAAAAB_wIAAAD_AgKAAyAAAAABgQMCAAAAAYIDAgAAAAGDAwEAAAABhAMgAAAAAYUDAQAAAAGGA0AAAAABAgAAAAEAICgAAMAHACADAAAABwAgKAAAwAcAICkAAMQHACAdAAAABwAgCgAA_wUAIBAAAIAGACASAACJBgAgFAAAgQYAIBUAAIIGACAXAACEBgAgGAAAhQYAIBkAAIYGACAaAACHBgAgGwAAiAYAICEAAMQHACCXAgEArAQAIacCQACxBAAhuAIAAL0EuAIiwAJAALEEACHyAgEArAQAIfoCAQCsBAAh-wIBALAEACH8AgEAsAQAIf0CAQCwBAAh_wIAAP4F_wIigAMgAMUEACGBAwIAuwQAIYIDAgC7BAAhgwMBALAEACGEAyAAxQQAIYUDAQCwBAAhhgNAANEEACEbCgAA_wUAIBAAAIAGACASAACJBgAgFAAAgQYAIBUAAIIGACAXAACEBgAgGAAAhQYAIBkAAIYGACAaAACHBgAgGwAAiAYAIJcCAQCsBAAhpwJAALEEACG4AgAAvQS4AiLAAkAAsQQAIfICAQCsBAAh-gIBAKwEACH7AgEAsAQAIfwCAQCwBAAh_QIBALAEACH_AgAA_gX_AiKAAyAAxQQAIYEDAgC7BAAhggMCALsEACGDAwEAsAQAIYQDIADFBAAhhQMBALAEACGGA0AA0QQAIQoEAADuBQAgBwAA7wUAIAoAAPEFACAQAADyBQAgEgAA8wUAIJcCAQAAAAGnAkAAAAABwAJAAAAAAcgCAQAAAAH2AgEAAAABAgAAAFwAICgAAMUHACADAAAACQAgKAAAxQcAICkAAMkHACAMAAAACQAgBAAArwUAIAcAALAFACAKAACyBQAgEAAAswUAIBIAALQFACAhAADJBwAglwIBAKwEACGnAkAAsQQAIcACQACxBAAhyAIBAKwEACH2AgEArAQAIQoEAACvBQAgBwAAsAUAIAoAALIFACAQAACzBQAgEgAAtAUAIJcCAQCsBAAhpwJAALEEACHAAkAAsQQAIcgCAQCsBAAh9gIBAKwEACEbCgAA4gYAIBAAAOMGACASAADsBgAgFAAA5AYAIBUAAOUGACAWAADmBgAgGAAA6AYAIBkAAOkGACAaAADqBgAgGwAA6wYAIJcCAQAAAAGnAkAAAAABuAIAAAC4AgLAAkAAAAAB8gIBAAAAAfoCAQAAAAH7AgEAAAAB_AIBAAAAAf0CAQAAAAH_AgAAAP8CAoADIAAAAAGBAwIAAAABggMCAAAAAYMDAQAAAAGEAyAAAAABhQMBAAAAAYYDQAAAAAECAAAAAQAgKAAAygcAIAMAAAAHACAoAADKBwAgKQAAzgcAIB0AAAAHACAKAAD_BQAgEAAAgAYAIBIAAIkGACAUAACBBgAgFQAAggYAIBYAAIMGACAYAACFBgAgGQAAhgYAIBoAAIcGACAbAACIBgAgIQAAzgcAIJcCAQCsBAAhpwJAALEEACG4AgAAvQS4AiLAAkAAsQQAIfICAQCsBAAh-gIBAKwEACH7AgEAsAQAIfwCAQCwBAAh_QIBALAEACH_AgAA_gX_AiKAAyAAxQQAIYEDAgC7BAAhggMCALsEACGDAwEAsAQAIYQDIADFBAAhhQMBALAEACGGA0AA0QQAIRsKAAD_BQAgEAAAgAYAIBIAAIkGACAUAACBBgAgFQAAggYAIBYAAIMGACAYAACFBgAgGQAAhgYAIBoAAIcGACAbAACIBgAglwIBAKwEACGnAkAAsQQAIbgCAAC9BLgCIsACQACxBAAh8gIBAKwEACH6AgEArAQAIfsCAQCwBAAh_AIBALAEACH9AgEAsAQAIf8CAAD-Bf8CIoADIADFBAAhgQMCALsEACGCAwIAuwQAIYMDAQCwBAAhhAMgAMUEACGFAwEAsAQAIYYDQADRBAAhGwoAAOIGACAQAADjBgAgEgAA7AYAIBQAAOQGACAVAADlBgAgFgAA5gYAIBcAAOcGACAYAADoBgAgGQAA6QYAIBsAAOsGACCXAgEAAAABpwJAAAAAAbgCAAAAuAICwAJAAAAAAfICAQAAAAH6AgEAAAAB-wIBAAAAAfwCAQAAAAH9AgEAAAAB_wIAAAD_AgKAAyAAAAABgQMCAAAAAYIDAgAAAAGDAwEAAAABhAMgAAAAAYUDAQAAAAGGA0AAAAABAgAAAAEAICgAAM8HACADAAAABwAgKAAAzwcAICkAANMHACAdAAAABwAgCgAA_wUAIBAAAIAGACASAACJBgAgFAAAgQYAIBUAAIIGACAWAACDBgAgFwAAhAYAIBgAAIUGACAZAACGBgAgGwAAiAYAICEAANMHACCXAgEArAQAIacCQACxBAAhuAIAAL0EuAIiwAJAALEEACHyAgEArAQAIfoCAQCsBAAh-wIBALAEACH8AgEAsAQAIf0CAQCwBAAh_wIAAP4F_wIigAMgAMUEACGBAwIAuwQAIYIDAgC7BAAhgwMBALAEACGEAyAAxQQAIYUDAQCwBAAhhgNAANEEACEbCgAA_wUAIBAAAIAGACASAACJBgAgFAAAgQYAIBUAAIIGACAWAACDBgAgFwAAhAYAIBgAAIUGACAZAACGBgAgGwAAiAYAIJcCAQCsBAAhpwJAALEEACG4AgAAvQS4AiLAAkAAsQQAIfICAQCsBAAh-gIBAKwEACH7AgEAsAQAIfwCAQCwBAAh_QIBALAEACH_AgAA_gX_AiKAAyAAxQQAIYEDAgC7BAAhggMCALsEACGDAwEAsAQAIYQDIADFBAAhhQMBALAEACGGA0AA0QQAIRsKAADiBgAgEAAA4wYAIBIAAOwGACAUAADkBgAgFQAA5QYAIBYAAOYGACAXAADnBgAgGAAA6AYAIBkAAOkGACAaAADqBgAglwIBAAAAAacCQAAAAAG4AgAAALgCAsACQAAAAAHyAgEAAAAB-gIBAAAAAfsCAQAAAAH8AgEAAAAB_QIBAAAAAf8CAAAA_wICgAMgAAAAAYEDAgAAAAGCAwIAAAABgwMBAAAAAYQDIAAAAAGFAwEAAAABhgNAAAAAAQIAAAABACAoAADUBwAgAwAAAAcAICgAANQHACApAADYBwAgHQAAAAcAIAoAAP8FACAQAACABgAgEgAAiQYAIBQAAIEGACAVAACCBgAgFgAAgwYAIBcAAIQGACAYAACFBgAgGQAAhgYAIBoAAIcGACAhAADYBwAglwIBAKwEACGnAkAAsQQAIbgCAAC9BLgCIsACQACxBAAh8gIBAKwEACH6AgEArAQAIfsCAQCwBAAh_AIBALAEACH9AgEAsAQAIf8CAAD-Bf8CIoADIADFBAAhgQMCALsEACGCAwIAuwQAIYMDAQCwBAAhhAMgAMUEACGFAwEAsAQAIYYDQADRBAAhGwoAAP8FACAQAACABgAgEgAAiQYAIBQAAIEGACAVAACCBgAgFgAAgwYAIBcAAIQGACAYAACFBgAgGQAAhgYAIBoAAIcGACCXAgEArAQAIacCQACxBAAhuAIAAL0EuAIiwAJAALEEACHyAgEArAQAIfoCAQCsBAAh-wIBALAEACH8AgEAsAQAIf0CAQCwBAAh_wIAAP4F_wIigAMgAMUEACGBAwIAuwQAIYIDAgC7BAAhgwMBALAEACGEAyAAxQQAIYUDAQCwBAAhhgNAANEEACEbCgAA4gYAIBAAAOMGACAUAADkBgAgFQAA5QYAIBYAAOYGACAXAADnBgAgGAAA6AYAIBkAAOkGACAaAADqBgAgGwAA6wYAIJcCAQAAAAGnAkAAAAABuAIAAAC4AgLAAkAAAAAB8gIBAAAAAfoCAQAAAAH7AgEAAAAB_AIBAAAAAf0CAQAAAAH_AgAAAP8CAoADIAAAAAGBAwIAAAABggMCAAAAAYMDAQAAAAGEAyAAAAABhQMBAAAAAYYDQAAAAAECAAAAAQAgKAAA2QcAIAoEAADuBQAgBwAA7wUAIAkAAPAFACAKAADxBQAgEAAA8gUAIJcCAQAAAAGnAkAAAAABwAJAAAAAAcgCAQAAAAH2AgEAAAABAgAAAFwAICgAANsHACADAAAABwAgKAAA2QcAICkAAN8HACAdAAAABwAgCgAA_wUAIBAAAIAGACAUAACBBgAgFQAAggYAIBYAAIMGACAXAACEBgAgGAAAhQYAIBkAAIYGACAaAACHBgAgGwAAiAYAICEAAN8HACCXAgEArAQAIacCQACxBAAhuAIAAL0EuAIiwAJAALEEACHyAgEArAQAIfoCAQCsBAAh-wIBALAEACH8AgEAsAQAIf0CAQCwBAAh_wIAAP4F_wIigAMgAMUEACGBAwIAuwQAIYIDAgC7BAAhgwMBALAEACGEAyAAxQQAIYUDAQCwBAAhhgNAANEEACEbCgAA_wUAIBAAAIAGACAUAACBBgAgFQAAggYAIBYAAIMGACAXAACEBgAgGAAAhQYAIBkAAIYGACAaAACHBgAgGwAAiAYAIJcCAQCsBAAhpwJAALEEACG4AgAAvQS4AiLAAkAAsQQAIfICAQCsBAAh-gIBAKwEACH7AgEAsAQAIfwCAQCwBAAh_QIBALAEACH_AgAA_gX_AiKAAyAAxQQAIYEDAgC7BAAhggMCALsEACGDAwEAsAQAIYQDIADFBAAhhQMBALAEACGGA0AA0QQAIQMAAAAJACAoAADbBwAgKQAA4gcAIAwAAAAJACAEAACvBQAgBwAAsAUAIAkAALEFACAKAACyBQAgEAAAswUAICEAAOIHACCXAgEArAQAIacCQACxBAAhwAJAALEEACHIAgEArAQAIfYCAQCsBAAhCgQAAK8FACAHAACwBQAgCQAAsQUAIAoAALIFACAQAACzBQAglwIBAKwEACGnAkAAsQQAIcACQACxBAAhyAIBAKwEACH2AgEArAQAIQwKBgIQKgYSPwkTABIULgwVMA0WMg4XNg8YNwMZOAQaOhAbPhEEAwgBCAoDECgGEwALBwQAAQcOBAkSBQoTAhAXBhIhCRMACgIFAAMGAAEBCAADBQgZAwsAAQwYAg4bBw8dCAENAAYBDQAGAggAAxEiAQUHIwAJJAAKJQAQJgASJwABECkAAQYAAQEGAAEBBgABAQYAAQEGAAEBBgABBgpAABBBABJFABRCABdDABtEAAAAAAUTABcuABgvABkwABoxABsAAAAAAAUTABcuABgvABkwABoxABsBBAABAQQAAQMTACAwACExACIAAAADEwAgMAAhMQAiAgUAAwYAAQIFAAMGAAEDEwAnMAAoMQApAAAAAxMAJzAAKDEAKQIDlAEBCJUBAwIDmwEBCJwBAwMTAC4wAC8xADAAAAADEwAuMAAvMQAwAwivAQMLAAEMrgECAwi2AQMLAAEMtQECBRMANS4ANi8ANzAAODEAOQAAAAAABRMANS4ANi8ANzAAODEAOQENAAYBDQAGBRMAPi4APy8AQDAAQTEAQgAAAAAABRMAPi4APy8AQDAAQTEAQgENAAYBDQAGBRMARy4ASC8ASTAASjEASwAAAAAABRMARy4ASC8ASTAASjEASwEGAAEBBgABAxMAUDAAUTEAUgAAAAMTAFAwAFExAFIBBgABAQYAAQMTAFcwAFgxAFkAAAADEwBXMABYMQBZAQYAAQEGAAEDEwBeMABfMQBgAAAAAxMAXjAAXzEAYAEIAAMBCAADAxMAZTAAZjEAZwAAAAMTAGUwAGYxAGcBBgABAQYAAQMTAGwwAG0xAG4AAAADEwBsMABtMQBuAQYAAQEGAAEDEwBzMAB0MQB1AAAAAxMAczAAdDEAdQEGAAEBBgABBRMAei4Aey8AfDAAfTEAfgAAAAAABRMAei4Aey8AfDAAfTEAfgIIAAMRmAMBAggAAxGeAwEDEwCDATAAhAExAIUBAAAAAxMAgwEwAIQBMQCFARwCAR1GAR5IAR9JASBKASJMASNOEyRPFCVRASZTEydUFSpVAStWASxXEzJaFjNbHDRdAzVeAzZgAzdhAzhiAzlkAzpmEztnHTxpAz1rEz5sHj9tA0BuA0FvE0JyH0NzI0R0BEV1BEZ2BEd3BEh4BEl6BEp8E0t9JEx_BE2BARNOggElT4MBBFCEAQRRhQETUogBJlOJASpUigECVYsBAlaMAQJXjQECWI4BAlmQAQJakgETW5MBK1yXAQJdmQETXpoBLF-dAQJgngECYZ8BE2KiAS1jowExZKQBBmWlAQZmpgEGZ6cBBmioAQZpqgEGaqwBE2utATJssQEGbbMBE260ATNvtwEGcLgBBnG5ARNyvAE0c70BOnS_AQd1wAEHdsIBB3fDAQd4xAEHecYBB3rIARN7yQE7fMsBB33NARN-zgE8f88BB4AB0AEHgQHRAROCAdQBPYMB1QFDhAHXAQiFAdgBCIYB2gEIhwHbAQiIAdwBCIkB3gEIigHgAROLAeEBRIwB4wEIjQHlAROOAeYBRY8B5wEIkAHoAQiRAekBE5IB7AFGkwHtAUyUAe4BDJUB7wEMlgHwAQyXAfEBDJgB8gEMmQH0AQyaAfYBE5sB9wFNnAH5AQydAfsBE54B_AFOnwH9AQygAf4BDKEB_wETogGCAk-jAYMCU6QBhQINpQGGAg2mAYgCDacBiQINqAGKAg2pAYwCDaoBjgITqwGPAlSsAZECDa0BkwITrgGUAlWvAZUCDbABlgINsQGXAhOyAZoCVrMBmwJatAGdAg61AZ4CDrYBoAIOtwGhAg64AaICDrkBpAIOugGmAhO7AacCW7wBqQIOvQGrAhO-AawCXL8BrQIOwAGuAg7BAa8CE8IBsgJdwwGzAmHEAbQCBcUBtQIFxgG2AgXHAbcCBcgBuAIFyQG6AgXKAbwCE8sBvQJizAG_AgXNAcECE84BwgJjzwHDAgXQAcQCBdEBxQIT0gHIAmTTAckCaNQBygIP1QHLAg_WAcwCD9cBzQIP2AHOAg_ZAdACD9oB0gIT2wHTAmncAdUCD90B1wIT3gHYAmrfAdkCD-AB2gIP4QHbAhPiAd4Ca-MB3wJv5AHhAhDlAeICEOYB5AIQ5wHlAhDoAeYCEOkB6AIQ6gHqAhPrAesCcOwB7QIQ7QHvAhPuAfACce8B8QIQ8AHyAhDxAfMCE_IB9gJy8wH3Anb0AfgCEfUB-QIR9gH6AhH3AfsCEfgB_AIR-QH-AhH6AYADE_sBgQN3_AGDAxH9AYUDE_4BhgN4_wGHAxGAAogDEYECiQMTggKMA3mDAo0Df4QCjgMJhQKPAwmGApADCYcCkQMJiAKSAwmJApQDCYoClgMTiwKXA4ABjAKaAwmNApwDE44CnQOBAY8CnwMJkAKgAwmRAqEDE5ICpAOCAZMCpQOGAQ" + strings: JSON.parse("[\"where\",\"orderBy\",\"cursor\",\"created_by\",\"owner\",\"org\",\"user\",\"members\",\"organization\",\"apiKeys\",\"patients\",\"uploaded_by\",\"patient\",\"scan\",\"scanImage\",\"report\",\"submittedBy\",\"assignedTo\",\"reanalysisScan\",\"reanalysisReport\",\"ticketsForReport\",\"ticketsAsReanalysis\",\"_count\",\"ticketsForScan\",\"scans\",\"actor\",\"auditLogs\",\"notifications\",\"emailNotification\",\"inAppNotification\",\"sessions\",\"ownedOrg\",\"orgMember\",\"subscription\",\"payments\",\"submittedTickets\",\"assignedTickets\",\"User.findUnique\",\"User.findUniqueOrThrow\",\"User.findFirst\",\"User.findFirstOrThrow\",\"User.findMany\",\"data\",\"User.createOne\",\"User.createMany\",\"User.createManyAndReturn\",\"User.updateOne\",\"User.updateMany\",\"User.updateManyAndReturn\",\"create\",\"update\",\"User.upsertOne\",\"User.deleteOne\",\"User.deleteMany\",\"having\",\"_avg\",\"_sum\",\"_min\",\"_max\",\"User.groupBy\",\"User.aggregate\",\"Organization.findUnique\",\"Organization.findUniqueOrThrow\",\"Organization.findFirst\",\"Organization.findFirstOrThrow\",\"Organization.findMany\",\"Organization.createOne\",\"Organization.createMany\",\"Organization.createManyAndReturn\",\"Organization.updateOne\",\"Organization.updateMany\",\"Organization.updateManyAndReturn\",\"Organization.upsertOne\",\"Organization.deleteOne\",\"Organization.deleteMany\",\"Organization.groupBy\",\"Organization.aggregate\",\"OrgMember.findUnique\",\"OrgMember.findUniqueOrThrow\",\"OrgMember.findFirst\",\"OrgMember.findFirstOrThrow\",\"OrgMember.findMany\",\"OrgMember.createOne\",\"OrgMember.createMany\",\"OrgMember.createManyAndReturn\",\"OrgMember.updateOne\",\"OrgMember.updateMany\",\"OrgMember.updateManyAndReturn\",\"OrgMember.upsertOne\",\"OrgMember.deleteOne\",\"OrgMember.deleteMany\",\"OrgMember.groupBy\",\"OrgMember.aggregate\",\"Patient.findUnique\",\"Patient.findUniqueOrThrow\",\"Patient.findFirst\",\"Patient.findFirstOrThrow\",\"Patient.findMany\",\"Patient.createOne\",\"Patient.createMany\",\"Patient.createManyAndReturn\",\"Patient.updateOne\",\"Patient.updateMany\",\"Patient.updateManyAndReturn\",\"Patient.upsertOne\",\"Patient.deleteOne\",\"Patient.deleteMany\",\"Patient.groupBy\",\"Patient.aggregate\",\"Scan.findUnique\",\"Scan.findUniqueOrThrow\",\"Scan.findFirst\",\"Scan.findFirstOrThrow\",\"Scan.findMany\",\"Scan.createOne\",\"Scan.createMany\",\"Scan.createManyAndReturn\",\"Scan.updateOne\",\"Scan.updateMany\",\"Scan.updateManyAndReturn\",\"Scan.upsertOne\",\"Scan.deleteOne\",\"Scan.deleteMany\",\"Scan.groupBy\",\"Scan.aggregate\",\"ScanImage.findUnique\",\"ScanImage.findUniqueOrThrow\",\"ScanImage.findFirst\",\"ScanImage.findFirstOrThrow\",\"ScanImage.findMany\",\"ScanImage.createOne\",\"ScanImage.createMany\",\"ScanImage.createManyAndReturn\",\"ScanImage.updateOne\",\"ScanImage.updateMany\",\"ScanImage.updateManyAndReturn\",\"ScanImage.upsertOne\",\"ScanImage.deleteOne\",\"ScanImage.deleteMany\",\"ScanImage.groupBy\",\"ScanImage.aggregate\",\"Report.findUnique\",\"Report.findUniqueOrThrow\",\"Report.findFirst\",\"Report.findFirstOrThrow\",\"Report.findMany\",\"Report.createOne\",\"Report.createMany\",\"Report.createManyAndReturn\",\"Report.updateOne\",\"Report.updateMany\",\"Report.updateManyAndReturn\",\"Report.upsertOne\",\"Report.deleteOne\",\"Report.deleteMany\",\"Report.groupBy\",\"Report.aggregate\",\"Notifications.findUnique\",\"Notifications.findUniqueOrThrow\",\"Notifications.findFirst\",\"Notifications.findFirstOrThrow\",\"Notifications.findMany\",\"Notifications.createOne\",\"Notifications.createMany\",\"Notifications.createManyAndReturn\",\"Notifications.updateOne\",\"Notifications.updateMany\",\"Notifications.updateManyAndReturn\",\"Notifications.upsertOne\",\"Notifications.deleteOne\",\"Notifications.deleteMany\",\"Notifications.groupBy\",\"Notifications.aggregate\",\"EmailNotification.findUnique\",\"EmailNotification.findUniqueOrThrow\",\"EmailNotification.findFirst\",\"EmailNotification.findFirstOrThrow\",\"EmailNotification.findMany\",\"EmailNotification.createOne\",\"EmailNotification.createMany\",\"EmailNotification.createManyAndReturn\",\"EmailNotification.updateOne\",\"EmailNotification.updateMany\",\"EmailNotification.updateManyAndReturn\",\"EmailNotification.upsertOne\",\"EmailNotification.deleteOne\",\"EmailNotification.deleteMany\",\"EmailNotification.groupBy\",\"EmailNotification.aggregate\",\"InAppNotification.findUnique\",\"InAppNotification.findUniqueOrThrow\",\"InAppNotification.findFirst\",\"InAppNotification.findFirstOrThrow\",\"InAppNotification.findMany\",\"InAppNotification.createOne\",\"InAppNotification.createMany\",\"InAppNotification.createManyAndReturn\",\"InAppNotification.updateOne\",\"InAppNotification.updateMany\",\"InAppNotification.updateManyAndReturn\",\"InAppNotification.upsertOne\",\"InAppNotification.deleteOne\",\"InAppNotification.deleteMany\",\"InAppNotification.groupBy\",\"InAppNotification.aggregate\",\"ApiKey.findUnique\",\"ApiKey.findUniqueOrThrow\",\"ApiKey.findFirst\",\"ApiKey.findFirstOrThrow\",\"ApiKey.findMany\",\"ApiKey.createOne\",\"ApiKey.createMany\",\"ApiKey.createManyAndReturn\",\"ApiKey.updateOne\",\"ApiKey.updateMany\",\"ApiKey.updateManyAndReturn\",\"ApiKey.upsertOne\",\"ApiKey.deleteOne\",\"ApiKey.deleteMany\",\"ApiKey.groupBy\",\"ApiKey.aggregate\",\"Session.findUnique\",\"Session.findUniqueOrThrow\",\"Session.findFirst\",\"Session.findFirstOrThrow\",\"Session.findMany\",\"Session.createOne\",\"Session.createMany\",\"Session.createManyAndReturn\",\"Session.updateOne\",\"Session.updateMany\",\"Session.updateManyAndReturn\",\"Session.upsertOne\",\"Session.deleteOne\",\"Session.deleteMany\",\"Session.groupBy\",\"Session.aggregate\",\"Subscription.findUnique\",\"Subscription.findUniqueOrThrow\",\"Subscription.findFirst\",\"Subscription.findFirstOrThrow\",\"Subscription.findMany\",\"Subscription.createOne\",\"Subscription.createMany\",\"Subscription.createManyAndReturn\",\"Subscription.updateOne\",\"Subscription.updateMany\",\"Subscription.updateManyAndReturn\",\"Subscription.upsertOne\",\"Subscription.deleteOne\",\"Subscription.deleteMany\",\"Subscription.groupBy\",\"Subscription.aggregate\",\"Payment.findUnique\",\"Payment.findUniqueOrThrow\",\"Payment.findFirst\",\"Payment.findFirstOrThrow\",\"Payment.findMany\",\"Payment.createOne\",\"Payment.createMany\",\"Payment.createManyAndReturn\",\"Payment.updateOne\",\"Payment.updateMany\",\"Payment.updateManyAndReturn\",\"Payment.upsertOne\",\"Payment.deleteOne\",\"Payment.deleteMany\",\"Payment.groupBy\",\"Payment.aggregate\",\"Ticket.findUnique\",\"Ticket.findUniqueOrThrow\",\"Ticket.findFirst\",\"Ticket.findFirstOrThrow\",\"Ticket.findMany\",\"Ticket.createOne\",\"Ticket.createMany\",\"Ticket.createManyAndReturn\",\"Ticket.updateOne\",\"Ticket.updateMany\",\"Ticket.updateManyAndReturn\",\"Ticket.upsertOne\",\"Ticket.deleteOne\",\"Ticket.deleteMany\",\"Ticket.groupBy\",\"Ticket.aggregate\",\"AuditLog.findUnique\",\"AuditLog.findUniqueOrThrow\",\"AuditLog.findFirst\",\"AuditLog.findFirstOrThrow\",\"AuditLog.findMany\",\"AuditLog.createOne\",\"AuditLog.createMany\",\"AuditLog.createManyAndReturn\",\"AuditLog.updateOne\",\"AuditLog.updateMany\",\"AuditLog.updateManyAndReturn\",\"AuditLog.upsertOne\",\"AuditLog.deleteOne\",\"AuditLog.deleteMany\",\"AuditLog.groupBy\",\"AuditLog.aggregate\",\"AND\",\"OR\",\"NOT\",\"id\",\"orgId\",\"actorId\",\"actorName\",\"actorEmail\",\"action\",\"AuditCategory\",\"category\",\"AuditStatus\",\"status\",\"AuditSeverity\",\"severity\",\"target\",\"targetId\",\"ip\",\"userAgent\",\"createdAt\",\"equals\",\"in\",\"notIn\",\"lt\",\"lte\",\"gt\",\"gte\",\"not\",\"contains\",\"startsWith\",\"endsWith\",\"code\",\"TicketType\",\"type\",\"TicketStatus\",\"TicketPriority\",\"priority\",\"reason\",\"scanId\",\"reportId\",\"submittedById\",\"assignedToId\",\"resolutionNote\",\"reanalysisScanId\",\"reanalysisReportId\",\"updatedAt\",\"resolvedAt\",\"userId\",\"amount\",\"PaymentStatus\",\"stripePaymentId\",\"Plan\",\"plan\",\"PaymentMode\",\"mode\",\"stripeCustomerId\",\"stripeSubscriptionId\",\"SubscriptionStatus\",\"currentPeriodEnd\",\"cancelAtPeriodEnd\",\"refreshToken\",\"deviceInfo\",\"ipAddress\",\"lastUsedAt\",\"expiresAt\",\"isRevoked\",\"organizationId\",\"name\",\"key\",\"scanReady\",\"reportReady\",\"productUpdates\",\"title\",\"message\",\"path\",\"NotificationType\",\"read\",\"content\",\"is_shared\",\"downloads\",\"share_token\",\"processing\",\"string_contains\",\"string_starts_with\",\"string_ends_with\",\"array_starts_with\",\"array_ends_with\",\"array_contains\",\"every\",\"some\",\"none\",\"url\",\"size\",\"resolution\",\"format\",\"scan_code\",\"notes\",\"Class\",\"class\",\"confidence_score\",\"all_scores\",\"Status\",\"uploadedById\",\"patientId\",\"cin\",\"full_name\",\"date_of_birth\",\"Gender\",\"gender\",\"email\",\"phone_number\",\"createdById\",\"isActive\",\"ownerId\",\"username\",\"password\",\"googleId\",\"profile_image_url\",\"Role\",\"role\",\"is_active\",\"total_scans\",\"total_reports\",\"twoFactorSecret\",\"twoFactorEnabled\",\"reset_password_token\",\"reset_token_expires\",\"is\",\"isNot\",\"connectOrCreate\",\"upsert\",\"createMany\",\"set\",\"disconnect\",\"delete\",\"connect\",\"updateMany\",\"deleteMany\",\"increment\",\"decrement\",\"multiply\",\"divide\"]"), + graph: "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_gIIAKsEACGMAwEAAAABjQMBAMwEACGPAwAA3QSPAyKQAwgAqwQAIZEDAACpBAAgkwMBAJQEACGUAwEAzAQAIQMAAAAUACABAAAVADACAAAWACABAAAAAwAgAQAAAAkAIA0NAACsBAAgrQIAAK8EADCuAgAAGgAQrwIAAK8EADCwAgEAlAQAIcACQACWBAAh0wIBAJQEACHaAkAAlgQAIfACAQCUBAAhiAMBAJQEACGJAwIAqgQAIYoDAQCUBAAhiwMBAJQEACEBAAAAGgAgEA0AAKwEACAUAACtBAAgFQAArQQAIK0CAACoBAAwrgIAABwAEK8CAACoBAAwsAIBAJQEACHAAkAAlgQAIcwCAQCUBAAh0wIBAJQEACHaAkAAlgQAIfoCAACpBAAg-wIgAJcEACH8AgIAqgQAIf0CAQDMBAAh_gIIAKsEACEBAAAAHAAgGQ0AANoEACAPAADbBAAgEAAAmAQAIBEAANQEACASAADaBAAgEwAA2wQAIK0CAADVBAAwrgIAAB4AEK8CAADVBAAwsAIBAJQEACG5AgAA1wTQAiLAAkAAlgQAIcwCAQCUBAAhzgIAANYEzgIi0QIAANgE0QIi0gIBAJQEACHTAgEAzAQAIdQCAQDMBAAh1QIBAJQEACHWAgEAzAQAIdcCAQDMBAAh2AIBAMwEACHZAgEAzAQAIdoCQACWBAAh2wJAANkEACENDQAA3gUAIA8AAJQIACAQAACiBQAgEQAAogUAIBIAAN4FACATAACUCAAg0wIAAO8EACDUAgAA7wQAINYCAADvBAAg1wIAAO8EACDYAgAA7wQAINkCAADvBAAg2wIAAO8EACAZDQAA2gQAIA8AANsEACAQAACYBAAgEQAA1AQAIBIAANoEACATAADbBAAgrQIAANUEADCuAgAAHgAQrwIAANUEADCwAgEAAAABuQIAANcE0AIiwAJAAJYEACHMAgEAAAABzgIAANYEzgIi0QIAANgE0QIi0gIBAJQEACHTAgEAzAQAIdQCAQDMBAAh1QIBAJQEACHWAgEAzAQAIdcCAQDMBAAh2AIBAMwEACHZAgEAzAQAIdoCQACWBAAh2wJAANkEACEDAAAAHgAgAQAAHwAwAgAAIAAgAQAAABQAIAEAAAAcACABAAAABwAgAQAAABQAIAEAAAAcACADAAAAHgAgAQAAHwAwAgAAIAAgAQAAAB4AIAEAAAAeACADAAAAHgAgAQAAHwAwAgAAIAAgAwAAAB4AIAEAAB8AMAIAACAAIAEAAAAeACABAAAAHgAgEwgAANMEACAZAADUBAAgrQIAAM8EADCuAgAALgAQrwIAAM8EADCwAgEAlAQAIbECAQDMBAAhsgIBAMwEACGzAgEAlAQAIbQCAQCUBAAhtQIBAJQEACG3AgAA0AS3AiK5AgAA0QS5AiK7AgAA0gS7AiK8AgEAlAQAIb0CAQDMBAAhvgIBAMwEACG_AgEAzAQAIcACQACWBAAhBwgAAJAIACAZAACiBQAgsQIAAO8EACCyAgAA7wQAIL0CAADvBAAgvgIAAO8EACC_AgAA7wQAIBMIAADTBAAgGQAA1AQAIK0CAADPBAAwrgIAAC4AEK8CAADPBAAwsAIBAAAAAbECAQDMBAAhsgIBAMwEACGzAgEAlAQAIbQCAQCUBAAhtQIBAJQEACG3AgAA0AS3AiK5AgAA0QS5AiK7AgAA0gS7AiK8AgEAlAQAIb0CAQDMBAAhvgIBAMwEACG_AgEAzAQAIcACQACWBAAhAwAAAC4AIAEAAC8AMAIAADAAIAEAAAAJACABAAAABwAgAQAAAAsAIAEAAAAPACABAAAAAwAgAQAAABQAIAEAAAAuACADAAAAFAAgAQAAFQAwAgAAFgAgAQAAABQAIAMAAAAUACABAAAVADACAAAWACANBgAAmAQAIK0CAADNBAAwrgIAADwAEK8CAADNBAAwsAIBAJQEACHAAkAAlgQAIc4CAADOBPkCItoCQACWBAAh3AIBAJQEACH1AgEAlAQAIfYCAQCUBAAh9wIBAMwEACH5AiAAlwQAIQIGAACiBQAg9wIAAO8EACANBgAAmAQAIK0CAADNBAAwrgIAADwAEK8CAADNBAAwsAIBAAAAAcACQACWBAAhzgIAAM4E-QIi2gJAAJYEACHcAgEAlAQAIfUCAQCUBAAh9gIBAJQEACH3AgEAzAQAIfkCIACXBAAhAwAAADwAIAEAAD0AMAIAAD4AIAsGAACYBAAgrQIAAJ4EADCuAgAAQAAQrwIAAJ4EADCwAgEAlAQAIcACQACWBAAh2gJAAJYEACHcAgEAlAQAIfICIACXBAAh8wIgAJcEACH0AiAAlwQAIQEAAABAACALBgAAmAQAIK0CAACcBAAwrgIAAEIAEK8CAACcBAAwsAIBAJQEACHAAkAAlgQAIdoCQACWBAAh3AIBAJQEACHyAiAAlwQAIfMCIACXBAAh9AIgAJcEACEBAAAAQgAgDgYAAJgEACCtAgAAywQAMK4CAABEABCvAgAAywQAMLACAQCUBAAhwAJAAJYEACHaAkAAlgQAIdwCAQCUBAAh6QIBAJQEACHqAgEAzAQAIesCAQDMBAAh7AJAAJYEACHtAkAAlgQAIe4CIACXBAAhAwYAAKIFACDqAgAA7wQAIOsCAADvBAAgDgYAAJgEACCtAgAAywQAMK4CAABEABCvAgAAywQAMLACAQAAAAHAAkAAlgQAIdoCQACWBAAh3AIBAJQEACHpAgEAAAAB6gIBAMwEACHrAgEAzAQAIewCQACWBAAh7QJAAJYEACHuAiAAlwQAIQMAAABEACABAABFADACAABGACABAAAACQAgAQAAAAsAIA0GAACYBAAgrQIAAJMEADCuAgAASgAQrwIAAJMEADCwAgEAlAQAIbkCAACVBOcCIsACQACWBAAh2gJAAJYEACHcAgEAlAQAIeQCAQCUBAAh5QIBAJQEACHnAkAAlgQAIegCIACXBAAhAQAAAEoAIAwGAACYBAAgrQIAAMcEADCuAgAATAAQrwIAAMcEADCwAgEAlAQAIbkCAADIBN8CIsACQACWBAAh3AIBAJQEACHdAgIAqgQAId8CAQCUBAAh4QIAAMkE4QIi4wIAAMoE4wIiAQYAAKIFACAMBgAAmAQAIK0CAADHBAAwrgIAAEwAEK8CAADHBAAwsAIBAAAAAbkCAADIBN8CIsACQACWBAAh3AIBAJQEACHdAgIAqgQAId8CAQCUBAAh4QIAAMkE4QIi4wIAAMoE4wIiAwAAAEwAIAEAAE0AMAIAAE4AIAMAAAAuACABAAAvADACAAAwACADAAAAHgAgAQAAHwAwAgAAIAAgAwAAAB4AIAEAAB8AMAIAACAAIAEAAAADACABAAAAFAAgAQAAADwAIAEAAABEACABAAAATAAgAQAAAC4AIAEAAAAeACABAAAAHgAgAQAAAAEAIBMKAAD_BgAgGAAAgAcAIBoAAIEHACAbAACMCAAgHAAAjQgAIB0AAI4IACAeAACPCAAgHwAAkAgAICAAAJEIACAhAACSCAAgIgAAkwgAICMAAN8FACAkAADfBQAgoAMAAO8EACChAwAA7wQAIKIDAADvBAAgqAMAAO8EACCqAwAA7wQAIKsDAADvBAAgAwAAAAcAIAEAAFwAMAIAAAEAIAMAAAAHACABAABcADACAAABACADAAAABwAgAQAAXAAwAgAAAQAgHgoAAP8HACAYAACACAAgGgAAiQgAIBsAAIEIACAcAACCCAAgHQAAgwgAIB4AAIQIACAfAACFCAAgIAAAhggAICEAAIcIACAiAACICAAgIwAAiggAICQAAIsIACCwAgEAAAABwAJAAAAAAdoCQAAAAAHhAgAAAOECApoDAQAAAAGfAwEAAAABoAMBAAAAAaEDAQAAAAGiAwEAAAABpAMAAACkAwKlAyAAAAABpgMCAAAAAacDAgAAAAGoAwEAAAABqQMgAAAAAaoDAQAAAAGrA0AAAAABASoAAGAAIBGwAgEAAAABwAJAAAAAAdoCQAAAAAHhAgAAAOECApoDAQAAAAGfAwEAAAABoAMBAAAAAaEDAQAAAAGiAwEAAAABpAMAAACkAwKlAyAAAAABpgMCAAAAAacDAgAAAAGoAwEAAAABqQMgAAAAAaoDAQAAAAGrA0AAAAABASoAAGIAMAEqAABiADAeCgAAiAcAIBgAAIkHACAaAACSBwAgGwAAigcAIBwAAIsHACAdAACMBwAgHgAAjQcAIB8AAI4HACAgAACPBwAgIQAAkAcAICIAAJEHACAjAACTBwAgJAAAlAcAILACAQDzBAAhwAJAAPgEACHaAkAA-AQAIeECAACXBeECIpoDAQDzBAAhnwMBAPMEACGgAwEA9wQAIaEDAQD3BAAhogMBAPcEACGkAwAAhwekAyKlAyAAnwUAIaYDAgCVBQAhpwMCAJUFACGoAwEA9wQAIakDIACfBQAhqgMBAPcEACGrA0AAgwUAIQIAAAABACAqAABlACARsAIBAPMEACHAAkAA-AQAIdoCQAD4BAAh4QIAAJcF4QIimgMBAPMEACGfAwEA8wQAIaADAQD3BAAhoQMBAPcEACGiAwEA9wQAIaQDAACHB6QDIqUDIACfBQAhpgMCAJUFACGnAwIAlQUAIagDAQD3BAAhqQMgAJ8FACGqAwEA9wQAIasDQACDBQAhAgAAAAcAICoAAGcAIAIAAAAHACAqAABnACADAAAAAQAgMQAAYAAgMgAAZQAgAQAAAAEAIAEAAAAHACALFgAAggcAIDcAAIMHACA4AACGBwAgOQAAhQcAIDoAAIQHACCgAwAA7wQAIKEDAADvBAAgogMAAO8EACCoAwAA7wQAIKoDAADvBAAgqwMAAO8EACAUrQIAAMMEADCuAgAAbgAQrwIAAMMEADCwAgEA3gMAIcACQADjAwAh2gJAAOMDACHhAgAAggThAiKaAwEA3gMAIZ8DAQDeAwAhoAMBAN8DACGhAwEA3wMAIaIDAQDfAwAhpAMAAMQEpAMipQMgAI4EACGmAwIAgAQAIacDAgCABAAhqAMBAN8DACGpAyAAjgQAIaoDAQDfAwAhqwNAAPYDACEDAAAABwAgAQAAbQAwNgAAbgAgAwAAAAcAIAEAAFwAMAIAAAEAIA4EAACYBAAgBwAAvgQAIAkAAL8EACAKAADABAAgGAAAwQQAIBoAAMIEACCtAgAAvQQAMK4CAAAJABCvAgAAvQQAMLACAQAAAAHAAkAAlgQAIdoCQACWBAAh8AIBAJQEACGeAwEAAAABAQAAAHEAIAEAAABxACAGBAAAogUAIAcAAP0GACAJAAD-BgAgCgAA_wYAIBgAAIAHACAaAACBBwAgAwAAAAkAIAEAAHQAMAIAAHEAIAMAAAAJACABAAB0ADACAABxACADAAAACQAgAQAAdAAwAgAAcQAgCwQAAPcGACAHAAD4BgAgCQAA-QYAIAoAAPoGACAYAAD7BgAgGgAA_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_gIIAAAAAYwDAQAAAAGNAwEAAAABjwMAAACPAwKQAwgAAAABkQOAAAAAAZMDAQAAAAGUAwEAAAABASoAAMABADABKgAAwAEAMAEAAAADACABAAAACQAgFQgAAPAFACALAADuBQAgDAAA7wUAIA4AAPEFACAPAADyBQAgFQAA9AUAIBcAAPMFACCwAgEA8wQAIbECAQD3BAAhuQIAAO0FkwMiwAJAAPgEACHaAkAA-AQAIfACAQD3BAAh_gIIAMIFACGMAwEA8wQAIY0DAQD3BAAhjwMAAOwFjwMikAMIAMIFACGRA4AAAAABkwMBAPMEACGUAwEA9wQAIQIAAAAWACAqAADFAQAgDrACAQDzBAAhsQIBAPcEACG5AgAA7QWTAyLAAkAA-AQAIdoCQAD4BAAh8AIBAPcEACH-AggAwgUAIYwDAQDzBAAhjQMBAPcEACGPAwAA7AWPAyKQAwgAwgUAIZEDgAAAAAGTAwEA8wQAIZQDAQD3BAAhAgAAABQAICoAAMcBACACAAAAFAAgKgAAxwEAIAEAAAADACABAAAACQAgAwAAABYAIDEAAL4BACAyAADFAQAgAQAAABYAIAEAAAAUACAJFgAA5wUAIDcAAOgFACA4AADrBQAgOQAA6gUAIDoAAOkFACCxAgAA7wQAIPACAADvBAAgjQMAAO8EACCUAwAA7wQAIBGtAgAAsAQAMK4CAADQAQAQrwIAALAEADCwAgEA3gMAIbECAQDfAwAhuQIAALIEkwMiwAJAAOMDACHaAkAA4wMAIfACAQDfAwAh_gIIAKUEACGMAwEA3gMAIY0DAQDfAwAhjwMAALEEjwMikAMIAKUEACGRAwAApAQAIJMDAQDeAwAhlAMBAN8DACEDAAAAFAAgAQAAzwEAMDYAANABACADAAAAFAAgAQAAFQAwAgAAFgAgDQ0AAKwEACCtAgAArwQAMK4CAAAaABCvAgAArwQAMLACAQAAAAHAAkAAlgQAIdMCAQAAAAHaAkAAlgQAIfACAQCUBAAhiAMBAJQEACGJAwIAqgQAIYoDAQCUBAAhiwMBAJQEACEBAAAA0wEAIAEAAADTAQAgAQ0AAN4FACADAAAAGgAgAQAA1gEAMAIAANMBACADAAAAGgAgAQAA1gEAMAIAANMBACADAAAAGgAgAQAA1gEAMAIAANMBACAKDQAA5gUAILACAQAAAAHAAkAAAAAB0wIBAAAAAdoCQAAAAAHwAgEAAAABiAMBAAAAAYkDAgAAAAGKAwEAAAABiwMBAAAAAQEqAADaAQAgCbACAQAAAAHAAkAAAAAB0wIBAAAAAdoCQAAAAAHwAgEAAAABiAMBAAAAAYkDAgAAAAGKAwEAAAABiwMBAAAAAQEqAADcAQAwASoAANwBADAKDQAA5QUAILACAQDzBAAhwAJAAPgEACHTAgEA8wQAIdoCQAD4BAAh8AIBAPMEACGIAwEA8wQAIYkDAgCVBQAhigMBAPMEACGLAwEA8wQAIQIAAADTAQAgKgAA3wEAIAmwAgEA8wQAIcACQAD4BAAh0wIBAPMEACHaAkAA-AQAIfACAQDzBAAhiAMBAPMEACGJAwIAlQUAIYoDAQDzBAAhiwMBAPMEACECAAAAGgAgKgAA4QEAIAIAAAAaACAqAADhAQAgAwAAANMBACAxAADaAQAgMgAA3wEAIAEAAADTAQAgAQAAABoAIAUWAADgBQAgNwAA4QUAIDgAAOQFACA5AADjBQAgOgAA4gUAIAytAgAArgQAMK4CAADoAQAQrwIAAK4EADCwAgEA3gMAIcACQADjAwAh0wIBAN4DACHaAkAA4wMAIfACAQDeAwAhiAMBAN4DACGJAwIAgAQAIYoDAQDeAwAhiwMBAN4DACEDAAAAGgAgAQAA5wEAMDYAAOgBACADAAAAGgAgAQAA1gEAMAIAANMBACAQDQAArAQAIBQAAK0EACAVAACtBAAgrQIAAKgEADCuAgAAHAAQrwIAAKgEADCwAgEAAAABwAJAAJYEACHMAgEAAAAB0wIBAAAAAdoCQACWBAAh-gIAAKkEACD7AiAAlwQAIfwCAgCqBAAh_QIBAAAAAf4CCACrBAAhAQAAAOsBACABAAAA6wEAIAQNAADeBQAgFAAA3wUAIBUAAN8FACD9AgAA7wQAIAMAAAAcACABAADuAQAwAgAA6wEAIAMAAAAcACABAADuAQAwAgAA6wEAIAMAAAAcACABAADuAQAwAgAA6wEAIA0NAADbBQAgFAAA3AUAIBUAAN0FACCwAgEAAAABwAJAAAAAAcwCAQAAAAHTAgEAAAAB2gJAAAAAAfoCgAAAAAH7AiAAAAAB_AICAAAAAf0CAQAAAAH-AggAAAABASoAAPIBACAKsAIBAAAAAcACQAAAAAHMAgEAAAAB0wIBAAAAAdoCQAAAAAH6AoAAAAAB-wIgAAAAAfwCAgAAAAH9AgEAAAAB_gIIAAAAAQEqAAD0AQAwASoAAPQBADANDQAAwwUAIBQAAMQFACAVAADFBQAgsAIBAPMEACHAAkAA-AQAIcwCAQDzBAAh0wIBAPMEACHaAkAA-AQAIfoCgAAAAAH7AiAAnwUAIfwCAgCVBQAh_QIBAPcEACH-AggAwgUAIQIAAADrAQAgKgAA9wEAIAqwAgEA8wQAIcACQAD4BAAhzAIBAPMEACHTAgEA8wQAIdoCQAD4BAAh-gKAAAAAAfsCIACfBQAh_AICAJUFACH9AgEA9wQAIf4CCADCBQAhAgAAABwAICoAAPkBACACAAAAHAAgKgAA-QEAIAMAAADrAQAgMQAA8gEAIDIAAPcBACABAAAA6wEAIAEAAAAcACAGFgAAvQUAIDcAAL4FACA4AADBBQAgOQAAwAUAIDoAAL8FACD9AgAA7wQAIA2tAgAAowQAMK4CAACAAgAQrwIAAKMEADCwAgEA3gMAIcACQADjAwAhzAIBAN4DACHTAgEA3gMAIdoCQADjAwAh-gIAAKQEACD7AiAAjgQAIfwCAgCABAAh_QIBAN8DACH-AggApQQAIQMAAAAcACABAAD_AQAwNgAAgAIAIAMAAAAcACABAADuAQAwAgAA6wEAIAEAAAA-ACABAAAAPgAgAwAAADwAIAEAAD0AMAIAAD4AIAMAAAA8ACABAAA9ADACAAA-ACADAAAAPAAgAQAAPQAwAgAAPgAgCgYAALwFACCwAgEAAAABwAJAAAAAAc4CAAAA-QIC2gJAAAAAAdwCAQAAAAH1AgEAAAAB9gIBAAAAAfcCAQAAAAH5AiAAAAABASoAAIgCACAJsAIBAAAAAcACQAAAAAHOAgAAAPkCAtoCQAAAAAHcAgEAAAAB9QIBAAAAAfYCAQAAAAH3AgEAAAAB-QIgAAAAAQEqAACKAgAwASoAAIoCADAKBgAAuwUAILACAQDzBAAhwAJAAPgEACHOAgAAugX5AiLaAkAA-AQAIdwCAQDzBAAh9QIBAPMEACH2AgEA8wQAIfcCAQD3BAAh-QIgAJ8FACECAAAAPgAgKgAAjQIAIAmwAgEA8wQAIcACQAD4BAAhzgIAALoF-QIi2gJAAPgEACHcAgEA8wQAIfUCAQDzBAAh9gIBAPMEACH3AgEA9wQAIfkCIACfBQAhAgAAADwAICoAAI8CACACAAAAPAAgKgAAjwIAIAMAAAA-ACAxAACIAgAgMgAAjQIAIAEAAAA-ACABAAAAPAAgBBYAALcFACA5AAC5BQAgOgAAuAUAIPcCAADvBAAgDK0CAACfBAAwrgIAAJYCABCvAgAAnwQAMLACAQDeAwAhwAJAAOMDACHOAgAAoAT5AiLaAkAA4wMAIdwCAQDeAwAh9QIBAN4DACH2AgEA3gMAIfcCAQDfAwAh-QIgAI4EACEDAAAAPAAgAQAAlQIAMDYAAJYCACADAAAAPAAgAQAAPQAwAgAAPgAgCwYAAJgEACCtAgAAngQAMK4CAABAABCvAgAAngQAMLACAQAAAAHAAkAAlgQAIdoCQACWBAAh3AIBAAAAAfICIACXBAAh8wIgAJcEACH0AiAAlwQAIQEAAACZAgAgAQAAAJkCACABBgAAogUAIAMAAABAACABAACcAgAwAgAAmQIAIAMAAABAACABAACcAgAwAgAAmQIAIAMAAABAACABAACcAgAwAgAAmQIAIAgGAAC2BQAgsAIBAAAAAcACQAAAAAHaAkAAAAAB3AIBAAAAAfICIAAAAAHzAiAAAAAB9AIgAAAAAQEqAACgAgAgB7ACAQAAAAHAAkAAAAAB2gJAAAAAAdwCAQAAAAHyAiAAAAAB8wIgAAAAAfQCIAAAAAEBKgAAogIAMAEqAACiAgAwCAYAALUFACCwAgEA8wQAIcACQAD4BAAh2gJAAPgEACHcAgEA8wQAIfICIACfBQAh8wIgAJ8FACH0AiAAnwUAIQIAAACZAgAgKgAApQIAIAewAgEA8wQAIcACQAD4BAAh2gJAAPgEACHcAgEA8wQAIfICIACfBQAh8wIgAJ8FACH0AiAAnwUAIQIAAABAACAqAACnAgAgAgAAAEAAICoAAKcCACADAAAAmQIAIDEAAKACACAyAAClAgAgAQAAAJkCACABAAAAQAAgAxYAALIFACA5AAC0BQAgOgAAswUAIAqtAgAAnQQAMK4CAACuAgAQrwIAAJ0EADCwAgEA3gMAIcACQADjAwAh2gJAAOMDACHcAgEA3gMAIfICIACOBAAh8wIgAI4EACH0AiAAjgQAIQMAAABAACABAACtAgAwNgAArgIAIAMAAABAACABAACcAgAwAgAAmQIAIAsGAACYBAAgrQIAAJwEADCuAgAAQgAQrwIAAJwEADCwAgEAAAABwAJAAJYEACHaAkAAlgQAIdwCAQAAAAHyAiAAlwQAIfMCIACXBAAh9AIgAJcEACEBAAAAsQIAIAEAAACxAgAgAQYAAKIFACADAAAAQgAgAQAAtAIAMAIAALECACADAAAAQgAgAQAAtAIAMAIAALECACADAAAAQgAgAQAAtAIAMAIAALECACAIBgAAsQUAILACAQAAAAHAAkAAAAAB2gJAAAAAAdwCAQAAAAHyAiAAAAAB8wIgAAAAAfQCIAAAAAEBKgAAuAIAIAewAgEAAAABwAJAAAAAAdoCQAAAAAHcAgEAAAAB8gIgAAAAAfMCIAAAAAH0AiAAAAABASoAALoCADABKgAAugIAMAgGAACwBQAgsAIBAPMEACHAAkAA-AQAIdoCQAD4BAAh3AIBAPMEACHyAiAAnwUAIfMCIACfBQAh9AIgAJ8FACECAAAAsQIAICoAAL0CACAHsAIBAPMEACHAAkAA-AQAIdoCQAD4BAAh3AIBAPMEACHyAiAAnwUAIfMCIACfBQAh9AIgAJ8FACECAAAAQgAgKgAAvwIAIAIAAABCACAqAAC_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-AIAMAIAAPUCACADAAAASgAgAQAA-AIAMAIAAPUCACADAAAASgAgAQAA-AIAMAIAAPUCACAKBgAAoQUAILACAQAAAAG5AgAAAOcCAsACQAAAAAHaAkAAAAAB3AIBAAAAAeQCAQAAAAHlAgEAAAAB5wJAAAAAAegCIAAAAAEBKgAA_AIAIAmwAgEAAAABuQIAAADnAgLAAkAAAAAB2gJAAAAAAdwCAQAAAAHkAgEAAAAB5QIBAAAAAecCQAAAAAHoAiAAAAABASoAAP4CADABKgAA_gIAMAoGAACgBQAgsAIBAPMEACG5AgAAngXnAiLAAkAA-AQAIdoCQAD4BAAh3AIBAPMEACHkAgEA8wQAIeUCAQDzBAAh5wJAAPgEACHoAiAAnwUAIQIAAAD1AgAgKgAAgQMAIAmwAgEA8wQAIbkCAACeBecCIsACQAD4BAAh2gJAAPgEACHcAgEA8wQAIeQCAQDzBAAh5QIBAPMEACHnAkAA-AQAIegCIACfBQAhAgAAAEoAICoAAIMDACACAAAASgAgKgAAgwMAIAMAAAD1AgAgMQAA_AIAIDIAAIEDACABAAAA9QIAIAEAAABKACADFgAAmwUAIDkAAJ0FACA6AACcBQAgDK0CAACMBAAwrgIAAIoDABCvAgAAjAQAMLACAQDeAwAhuQIAAI0E5wIiwAJAAOMDACHaAkAA4wMAIdwCAQDeAwAh5AIBAN4DACHlAgEA3gMAIecCQADjAwAh6AIgAI4EACEDAAAASgAgAQAAiQMAMDYAAIoDACADAAAASgAgAQAA-AIAMAIAAPUCACABAAAATgAgAQAAAE4AIAMAAABMACABAABNADACAABOACADAAAATAAgAQAATQAwAgAATgAgAwAAAEwAIAEAAE0AMAIAAE4AIAkGAACaBQAgsAIBAAAAAbkCAAAA3wICwAJAAAAAAdwCAQAAAAHdAgIAAAAB3wIBAAAAAeECAAAA4QIC4wIAAADjAgIBKgAAkgMAIAiwAgEAAAABuQIAAADfAgLAAkAAAAAB3AIBAAAAAd0CAgAAAAHfAgEAAAAB4QIAAADhAgLjAgAAAOMCAgEqAACUAwAwASoAAJQDADAJBgAAmQUAILACAQDzBAAhuQIAAJYF3wIiwAJAAPgEACHcAgEA8wQAId0CAgCVBQAh3wIBAPMEACHhAgAAlwXhAiLjAgAAmAXjAiICAAAATgAgKgAAlwMAIAiwAgEA8wQAIbkCAACWBd8CIsACQAD4BAAh3AIBAPMEACHdAgIAlQUAId8CAQDzBAAh4QIAAJcF4QIi4wIAAJgF4wIiAgAAAEwAICoAAJkDACACAAAATAAgKgAAmQMAIAMAAABOACAxAACSAwAgMgAAlwMAIAEAAABOACABAAAATAAgBRYAAJAFACA3AACRBQAgOAAAlAUAIDkAAJMFACA6AACSBQAgC60CAAD_AwAwrgIAAKADABCvAgAA_wMAMLACAQDeAwAhuQIAAIEE3wIiwAJAAOMDACHcAgEA3gMAId0CAgCABAAh3wIBAN4DACHhAgAAggThAiLjAgAAgwTjAiIDAAAATAAgAQAAnwMAMDYAAKADACADAAAATAAgAQAATQAwAgAATgAgAQAAACAAIAEAAAAgACADAAAAHgAgAQAAHwAwAgAAIAAgAwAAAB4AIAEAAB8AMAIAACAAIAMAAAAeACABAAAfADACAAAgACAWDQAAigUAIA8AAIsFACAQAACMBQAgEQAAjQUAIBIAAI4FACATAACPBQAgsAIBAAAAAbkCAAAA0AICwAJAAAAAAcwCAQAAAAHOAgAAAM4CAtECAAAA0QIC0gIBAAAAAdMCAQAAAAHUAgEAAAAB1QIBAAAAAdYCAQAAAAHXAgEAAAAB2AIBAAAAAdkCAQAAAAHaAkAAAAAB2wJAAAAAAQEqAACoAwAgELACAQAAAAG5AgAAANACAsACQAAAAAHMAgEAAAABzgIAAADOAgLRAgAAANECAtICAQAAAAHTAgEAAAAB1AIBAAAAAdUCAQAAAAHWAgEAAAAB1wIBAAAAAdgCAQAAAAHZAgEAAAAB2gJAAAAAAdsCQAAAAAEBKgAAqgMAMAEqAACqAwAwAQAAABQAIAEAAAAcACABAAAABwAgAQAAABQAIAEAAAAcACAWDQAAhAUAIA8AAIUFACAQAACGBQAgEQAAhwUAIBIAAIgFACATAACJBQAgsAIBAPMEACG5AgAAgQXQAiLAAkAA-AQAIcwCAQDzBAAhzgIAAIAFzgIi0QIAAIIF0QIi0gIBAPMEACHTAgEA9wQAIdQCAQD3BAAh1QIBAPMEACHWAgEA9wQAIdcCAQD3BAAh2AIBAPcEACHZAgEA9wQAIdoCQAD4BAAh2wJAAIMFACECAAAAIAAgKgAAsgMAIBCwAgEA8wQAIbkCAACBBdACIsACQAD4BAAhzAIBAPMEACHOAgAAgAXOAiLRAgAAggXRAiLSAgEA8wQAIdMCAQD3BAAh1AIBAPcEACHVAgEA8wQAIdYCAQD3BAAh1wIBAPcEACHYAgEA9wQAIdkCAQD3BAAh2gJAAPgEACHbAkAAgwUAIQIAAAAeACAqAAC0AwAgAgAAAB4AICoAALQDACABAAAAFAAgAQAAABwAIAEAAAAHACABAAAAFAAgAQAAABwAIAMAAAAgACAxAACoAwAgMgAAsgMAIAEAAAAgACABAAAAHgAgChYAAP0EACA5AAD_BAAgOgAA_gQAINMCAADvBAAg1AIAAO8EACDWAgAA7wQAINcCAADvBAAg2AIAAO8EACDZAgAA7wQAINsCAADvBAAgE60CAADyAwAwrgIAAMADABCvAgAA8gMAMLACAQDeAwAhuQIAAPQD0AIiwAJAAOMDACHMAgEA3gMAIc4CAADzA84CItECAAD1A9ECItICAQDeAwAh0wIBAN8DACHUAgEA3wMAIdUCAQDeAwAh1gIBAN8DACHXAgEA3wMAIdgCAQDfAwAh2QIBAN8DACHaAkAA4wMAIdsCQAD2AwAhAwAAAB4AIAEAAL8DADA2AADAAwAgAwAAAB4AIAEAAB8AMAIAACAAIAEAAAAwACABAAAAMAAgAwAAAC4AIAEAAC8AMAIAADAAIAMAAAAuACABAAAvADACAAAwACADAAAALgAgAQAALwAwAgAAMAAgEAgAAPsEACAZAAD8BAAgsAIBAAAAAbECAQAAAAGyAgEAAAABswIBAAAAAbQCAQAAAAG1AgEAAAABtwIAAAC3AgK5AgAAALkCArsCAAAAuwICvAIBAAAAAb0CAQAAAAG-AgEAAAABvwIBAAAAAcACQAAAAAEBKgAAyAMAIA6wAgEAAAABsQIBAAAAAbICAQAAAAGzAgEAAAABtAIBAAAAAbUCAQAAAAG3AgAAALcCArkCAAAAuQICuwIAAAC7AgK8AgEAAAABvQIBAAAAAb4CAQAAAAG_AgEAAAABwAJAAAAAAQEqAADKAwAwASoAAMoDADABAAAACQAgAQAAAAcAIBAIAAD5BAAgGQAA-gQAILACAQDzBAAhsQIBAPcEACGyAgEA9wQAIbMCAQDzBAAhtAIBAPMEACG1AgEA8wQAIbcCAAD0BLcCIrkCAAD1BLkCIrsCAAD2BLsCIrwCAQDzBAAhvQIBAPcEACG-AgEA9wQAIb8CAQD3BAAhwAJAAPgEACECAAAAMAAgKgAAzwMAIA6wAgEA8wQAIbECAQD3BAAhsgIBAPcEACGzAgEA8wQAIbQCAQDzBAAhtQIBAPMEACG3AgAA9AS3AiK5AgAA9QS5AiK7AgAA9gS7AiK8AgEA8wQAIb0CAQD3BAAhvgIBAPcEACG_AgEA9wQAIcACQAD4BAAhAgAAAC4AICoAANEDACACAAAALgAgKgAA0QMAIAEAAAAJACABAAAABwAgAwAAADAAIDEAAMgDACAyAADPAwAgAQAAADAAIAEAAAAuACAIFgAA8AQAIDkAAPIEACA6AADxBAAgsQIAAO8EACCyAgAA7wQAIL0CAADvBAAgvgIAAO8EACC_AgAA7wQAIBGtAgAA3QMAMK4CAADaAwAQrwIAAN0DADCwAgEA3gMAIbECAQDfAwAhsgIBAN8DACGzAgEA3gMAIbQCAQDeAwAhtQIBAN4DACG3AgAA4AO3AiK5AgAA4QO5AiK7AgAA4gO7AiK8AgEA3gMAIb0CAQDfAwAhvgIBAN8DACG_AgEA3wMAIcACQADjAwAhAwAAAC4AIAEAANkDADA2AADaAwAgAwAAAC4AIAEAAC8AMAIAADAAIBGtAgAA3QMAMK4CAADaAwAQrwIAAN0DADCwAgEA3gMAIbECAQDfAwAhsgIBAN8DACGzAgEA3gMAIbQCAQDeAwAhtQIBAN4DACG3AgAA4AO3AiK5AgAA4QO5AiK7AgAA4gO7AiK8AgEA3gMAIb0CAQDfAwAhvgIBAN8DACG_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_AMAIMECAAAA0AICwgIAAADQAgjDAgAAANACCMgCAAD7A9ACIgcWAADlAwAgOQAA-gMAIDoAAPoDACDBAgAAANECAsICAAAA0QIIwwIAAADRAgjIAgAA-QPRAiILFgAA7gMAIDkAAPgDACA6AAD4AwAgwQJAAAAAAcICQAAAAAXDAkAAAAAFxAJAAAAAAcUCQAAAAAHGAkAAAAABxwJAAAAAAcgCQAD3AwAhCxYAAO4DACA5AAD4AwAgOgAA-AMAIMECQAAAAAHCAkAAAAAFwwJAAAAABcQCQAAAAAHFAkAAAAABxgJAAAAAAccCQAAAAAHIAkAA9wMAIQjBAkAAAAABwgJAAAAABcMCQAAAAAXEAkAAAAABxQJAAAAAAcYCQAAAAAHHAkAAAAAByAJAAPgDACEHFgAA5QMAIDkAAPoDACA6AAD6AwAgwQIAAADRAgLCAgAAANECCMMCAAAA0QIIyAIAAPkD0QIiBMECAAAA0QICwgIAAADRAgjDAgAAANECCMgCAAD6A9ECIgcWAADlAwAgOQAA_AMAIDoAAPwDACDBAgAAANACAsICAAAA0AIIwwIAAADQAgjIAgAA-wPQAiIEwQIAAADQAgLCAgAAANACCMMCAAAA0AIIyAIAAPwD0AIiBxYAAOUDACA5AAD-AwAgOgAA_gMAIMECAAAAzgICwgIAAADOAgjDAgAAAM4CCMgCAAD9A84CIgTBAgAAAM4CAsICAAAAzgIIwwIAAADOAgjIAgAA_gPOAiILrQIAAP8DADCuAgAAoAMAEK8CAAD_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-QIIyAIAAKIE-QIiDa0CAACjBAAwrgIAAIACABCvAgAAowQAMLACAQDeAwAhwAJAAOMDACHMAgEA3gMAIdMCAQDeAwAh2gJAAOMDACH6AgAApAQAIPsCIACOBAAh_AICAIAEACH9AgEA3wMAIf4CCAClBAAhDxYAAOUDACA5AACnBAAgOgAApwQAIMECgAAAAAHEAoAAAAABxQKAAAAAAcYCgAAAAAHHAoAAAAAByAKAAAAAAf8CAQAAAAGAAwEAAAABgQMBAAAAAYIDgAAAAAGDA4AAAAABhAOAAAAAAQ0WAADlAwAgNwAAiwQAIDgAAIsEACA5AACLBAAgOgAAiwQAIMECCAAAAAHCAggAAAAEwwIIAAAABMQCCAAAAAHFAggAAAABxgIIAAAAAccCCAAAAAHIAggApgQAIQ0WAADlAwAgNwAAiwQAIDgAAIsEACA5AACLBAAgOgAAiwQAIMECCAAAAAHCAggAAAAEwwIIAAAABMQCCAAAAAHFAggAAAABxgIIAAAAAccCCAAAAAHIAggApgQAIQzBAoAAAAABxAKAAAAAAcUCgAAAAAHGAoAAAAABxwKAAAAAAcgCgAAAAAH_AgEAAAABgAMBAAAAAYEDAQAAAAGCA4AAAAABgwOAAAAAAYQDgAAAAAEQDQAArAQAIBQAAK0EACAVAACtBAAgrQIAAKgEADCuAgAAHAAQrwIAAKgEADCwAgEAlAQAIcACQACWBAAhzAIBAJQEACHTAgEAlAQAIdoCQACWBAAh-gIAAKkEACD7AiAAlwQAIfwCAgCqBAAh_QIBAMwEACH-AggAqwQAIQzBAoAAAAABxAKAAAAAAcUCgAAAAAHGAoAAAAABxwKAAAAAAcgCgAAAAAH_AgEAAAABgAMBAAAAAYEDAQAAAAGCA4AAAAABgwOAAAAAAYQDgAAAAAEIwQICAAAAAcICAgAAAATDAgIAAAAExAICAAAAAcUCAgAAAAHGAgIAAAABxwICAAAAAcgCAgDlAwAhCMECCAAAAAHCAggAAAAEwwIIAAAABMQCCAAAAAHFAggAAAABxgIIAAAAAccCCAAAAAHIAggAiwQAIRoIAADTBAAgCwAAmAQAIAwAAN8EACAOAADgBAAgDwAA2wQAIBUAAK0EACAXAACtBAAgrQIAANwEADCuAgAAFAAQrwIAANwEADCwAgEAlAQAIbECAQDMBAAhuQIAAN4EkwMiwAJAAJYEACHaAkAAlgQAIfACAQDMBAAh_gIIAKsEACGMAwEAlAQAIY0DAQDMBAAhjwMAAN0EjwMikAMIAKsEACGRAwAAqQQAIJMDAQCUBAAhlAMBAMwEACGsAwAAFAAgrQMAABQAIAOFAwAAHgAghgMAAB4AIIcDAAAeACAMrQIAAK4EADCuAgAA6AEAEK8CAACuBAAwsAIBAN4DACHAAkAA4wMAIdMCAQDeAwAh2gJAAOMDACHwAgEA3gMAIYgDAQDeAwAhiQMCAIAEACGKAwEA3gMAIYsDAQDeAwAhDQ0AAKwEACCtAgAArwQAMK4CAAAaABCvAgAArwQAMLACAQCUBAAhwAJAAJYEACHTAgEAlAQAIdoCQACWBAAh8AIBAJQEACGIAwEAlAQAIYkDAgCqBAAhigMBAJQEACGLAwEAlAQAIRGtAgAAsAQAMK4CAADQAQAQrwIAALAEADCwAgEA3gMAIbECAQDfAwAhuQIAALIEkwMiwAJAAOMDACHaAkAA4wMAIfACAQDfAwAh_gIIAKUEACGMAwEA3gMAIY0DAQDfAwAhjwMAALEEjwMikAMIAKUEACGRAwAApAQAIJMDAQDeAwAhlAMBAN8DACEHFgAA5QMAIDkAALYEACA6AAC2BAAgwQIAAACPAwLCAgAAAI8DCMMCAAAAjwMIyAIAALUEjwMiBxYAAOUDACA5AAC0BAAgOgAAtAQAIMECAAAAkwMCwgIAAACTAwjDAgAAAJMDCMgCAACzBJMDIgcWAADlAwAgOQAAtAQAIDoAALQEACDBAgAAAJMDAsICAAAAkwMIwwIAAACTAwjIAgAAswSTAyIEwQIAAACTAwLCAgAAAJMDCMMCAAAAkwMIyAIAALQEkwMiBxYAAOUDACA5AAC2BAAgOgAAtgQAIMECAAAAjwMCwgIAAACPAwjDAgAAAI8DCMgCAAC1BI8DIgTBAgAAAI8DAsICAAAAjwMIwwIAAACPAwjIAgAAtgSPAyIOrQIAALcEADCuAgAAtgEAEK8CAAC3BAAwsAIBAN4DACGxAgEA3wMAIcACQADjAwAh2gJAAOMDACGVAwEA3gMAIZYDAQDeAwAhlwMBAN4DACGZAwAAuASZAyKaAwEA3gMAIZsDAQDeAwAhnAMBAN8DACEHFgAA5QMAIDkAALoEACA6AAC6BAAgwQIAAACZAwLCAgAAAJkDCMMCAAAAmQMIyAIAALkEmQMiBxYAAOUDACA5AAC6BAAgOgAAugQAIMECAAAAmQMCwgIAAACZAwjDAgAAAJkDCMgCAAC5BJkDIgTBAgAAAJkDAsICAAAAmQMIwwIAAACZAwjIAgAAugSZAyIJrQIAALsEADCuAgAAnAEAEK8CAAC7BAAwsAIBAN4DACGxAgEA3gMAIcACQADjAwAh2gJAAOMDACHcAgEA3gMAIZ0DIACOBAAhCK0CAAC8BAAwrgIAAIYBABCvAgAAvAQAMLACAQDeAwAhwAJAAOMDACHaAkAA4wMAIfACAQDeAwAhngMBAN4DACEOBAAAmAQAIAcAAL4EACAJAAC_BAAgCgAAwAQAIBgAAMEEACAaAADCBAAgrQIAAL0EADCuAgAACQAQrwIAAL0EADCwAgEAlAQAIcACQACWBAAh2gJAAJYEACHwAgEAlAQAIZ4DAQCUBAAhA4UDAAALACCGAwAACwAghwMAAAsAIAOFAwAADwAghgMAAA8AIIcDAAAPACADhQMAAAMAIIYDAAADACCHAwAAAwAgA4UDAAAUACCGAwAAFAAghwMAABQAIAOFAwAALgAghgMAAC4AIIcDAAAuACAUrQIAAMMEADCuAgAAbgAQrwIAAMMEADCwAgEA3gMAIcACQADjAwAh2gJAAOMDACHhAgAAggThAiKaAwEA3gMAIZ8DAQDeAwAhoAMBAN8DACGhAwEA3wMAIaIDAQDfAwAhpAMAAMQEpAMipQMgAI4EACGmAwIAgAQAIacDAgCABAAhqAMBAN8DACGpAyAAjgQAIaoDAQDfAwAhqwNAAPYDACEHFgAA5QMAIDkAAMYEACA6AADGBAAgwQIAAACkAwLCAgAAAKQDCMMCAAAApAMIyAIAAMUEpAMiBxYAAOUDACA5AADGBAAgOgAAxgQAIMECAAAApAMCwgIAAACkAwjDAgAAAKQDCMgCAADFBKQDIgTBAgAAAKQDAsICAAAApAMIwwIAAACkAwjIAgAAxgSkAyIMBgAAmAQAIK0CAADHBAAwrgIAAEwAEK8CAADHBAAwsAIBAJQEACG5AgAAyATfAiLAAkAAlgQAIdwCAQCUBAAh3QICAKoEACHfAgEAlAQAIeECAADJBOECIuMCAADKBOMCIgTBAgAAAN8CAsICAAAA3wIIwwIAAADfAgjIAgAAiQTfAiIEwQIAAADhAgLCAgAAAOECCMMCAAAA4QIIyAIAAIcE4QIiBMECAAAA4wICwgIAAADjAgjDAgAAAOMCCMgCAACFBOMCIg4GAACYBAAgrQIAAMsEADCuAgAARAAQrwIAAMsEADCwAgEAlAQAIcACQACWBAAh2gJAAJYEACHcAgEAlAQAIekCAQCUBAAh6gIBAMwEACHrAgEAzAQAIewCQACWBAAh7QJAAJYEACHuAiAAlwQAIQvBAgEAAAABwgIBAAAABcMCAQAAAAXEAgEAAAABxQIBAAAAAcYCAQAAAAHHAgEAAAAByAIBAO8DACHJAgEAAAABygIBAAAAAcsCAQAAAAENBgAAmAQAIK0CAADNBAAwrgIAADwAEK8CAADNBAAwsAIBAJQEACHAAkAAlgQAIc4CAADOBPkCItoCQACWBAAh3AIBAJQEACH1AgEAlAQAIfYCAQCUBAAh9wIBAMwEACH5AiAAlwQAIQTBAgAAAPkCAsICAAAA-QIIwwIAAAD5AgjIAgAAogT5AiITCAAA0wQAIBkAANQEACCtAgAAzwQAMK4CAAAuABCvAgAAzwQAMLACAQCUBAAhsQIBAMwEACGyAgEAzAQAIbMCAQCUBAAhtAIBAJQEACG1AgEAlAQAIbcCAADQBLcCIrkCAADRBLkCIrsCAADSBLsCIrwCAQCUBAAhvQIBAMwEACG-AgEAzAQAIb8CAQDMBAAhwAJAAJYEACEEwQIAAAC3AgLCAgAAALcCCMMCAAAAtwIIyAIAAOwDtwIiBMECAAAAuQICwgIAAAC5AgjDAgAAALkCCMgCAADqA7kCIgTBAgAAALsCAsICAAAAuwIIwwIAAAC7AgjIAgAA6AO7AiIQBAAAmAQAIAcAAL4EACAJAAC_BAAgCgAAwAQAIBgAAMEEACAaAADCBAAgrQIAAL0EADCuAgAACQAQrwIAAL0EADCwAgEAlAQAIcACQACWBAAh2gJAAJYEACHwAgEAlAQAIZ4DAQCUBAAhrAMAAAkAIK0DAAAJACAjCgAAwAQAIBgAAMEEACAaAADCBAAgGwAA5gQAIBwAAOcEACAdAADoBAAgHgAA6QQAIB8AANMEACAgAADqBAAgIQAA6wQAICIAAOwEACAjAACtBAAgJAAArQQAIK0CAADkBAAwrgIAAAcAEK8CAADkBAAwsAIBAJQEACHAAkAAlgQAIdoCQACWBAAh4QIAAMkE4QIimgMBAJQEACGfAwEAlAQAIaADAQDMBAAhoQMBAMwEACGiAwEAzAQAIaQDAADlBKQDIqUDIACXBAAhpgMCAKoEACGnAwIAqgQAIagDAQDMBAAhqQMgAJcEACGqAwEAzAQAIasDQADZBAAhrAMAAAcAIK0DAAAHACAZDQAA2gQAIA8AANsEACAQAACYBAAgEQAA1AQAIBIAANoEACATAADbBAAgrQIAANUEADCuAgAAHgAQrwIAANUEADCwAgEAlAQAIbkCAADXBNACIsACQACWBAAhzAIBAJQEACHOAgAA1gTOAiLRAgAA2ATRAiLSAgEAlAQAIdMCAQDMBAAh1AIBAMwEACHVAgEAlAQAIdYCAQDMBAAh1wIBAMwEACHYAgEAzAQAIdkCAQDMBAAh2gJAAJYEACHbAkAA2QQAIQTBAgAAAM4CAsICAAAAzgIIwwIAAADOAgjIAgAA_gPOAiIEwQIAAADQAgLCAgAAANACCMMCAAAA0AIIyAIAAPwD0AIiBMECAAAA0QICwgIAAADRAgjDAgAAANECCMgCAAD6A9ECIgjBAkAAAAABwgJAAAAABcMCQAAAAAXEAkAAAAABxQJAAAAAAcYCQAAAAAHHAkAAAAAByAJAAPgDACEaCAAA0wQAIAsAAJgEACAMAADfBAAgDgAA4AQAIA8AANsEACAVAACtBAAgFwAArQQAIK0CAADcBAAwrgIAABQAEK8CAADcBAAwsAIBAJQEACGxAgEAzAQAIbkCAADeBJMDIsACQACWBAAh2gJAAJYEACHwAgEAzAQAIf4CCACrBAAhjAMBAJQEACGNAwEAzAQAIY8DAADdBI8DIpADCACrBAAhkQMAAKkEACCTAwEAlAQAIZQDAQDMBAAhrAMAABQAIK0DAAAUACASDQAArAQAIBQAAK0EACAVAACtBAAgrQIAAKgEADCuAgAAHAAQrwIAAKgEADCwAgEAlAQAIcACQACWBAAhzAIBAJQEACHTAgEAlAQAIdoCQACWBAAh-gIAAKkEACD7AiAAlwQAIfwCAgCqBAAh_QIBAMwEACH-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-wgAILQDAAABACADMQAA-QgAIK4DAAD6CAAgtAMAAAEAIAAAAAGxAwAAAOcCAgGxAyAAAAABBTEAAPQIACAyAAD3CAAgrgMAAPUIACCvAwAA9ggAILQDAAABACADMQAA9AgAIK4DAAD1CAAgtAMAAAEAIBMKAAD_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_gUAMDIAAIIGADCuAwAA_wUAMK8DAACABgAwsAMAAIEGACCxAwAAygUAMLIDAADKBQAwswMAAMoFADC0AwAAygUAMLUDAACDBgAwtgMAAM0FADALMQAA9QUAMDIAAPkFADCuAwAA9gUAMK8DAAD3BQAwsAMAAPgFACCxAwAAygUAMLIDAADKBQAwswMAAMoFADC0AwAAygUAMLUDAAD6BQAwtgMAAM0FADAUDQAAigUAIA8AAIsFACAQAACMBQAgEQAAjQUAIBMAAI8FACCwAgEAAAABuQIAAADQAgLAAkAAAAABzAIBAAAAAc4CAAAAzgIC0QIAAADRAgLSAgEAAAAB0wIBAAAAAdQCAQAAAAHVAgEAAAAB1gIBAAAAAdcCAQAAAAHZAgEAAAAB2gJAAAAAAdsCQAAAAAECAAAAIAAgMQAA_QUAIAMAAAAgACAxAAD9BQAgMgAA_AUAIAEqAADFCAAwAgAAACAAICoAAPwFACACAAAAzgUAICoAAPsFACAPsAIBAPMEACG5AgAAgQXQAiLAAkAA-AQAIcwCAQDzBAAhzgIAAIAFzgIi0QIAAIIF0QIi0gIBAPMEACHTAgEA9wQAIdQCAQD3BAAh1QIBAPMEACHWAgEA9wQAIdcCAQD3BAAh2QIBAPcEACHaAkAA-AQAIdsCQACDBQAhFA0AAIQFACAPAACFBQAgEAAAhgUAIBEAAIcFACATAACJBQAgsAIBAPMEACG5AgAAgQXQAiLAAkAA-AQAIcwCAQDzBAAhzgIAAIAFzgIi0QIAAIIF0QIi0gIBAPMEACHTAgEA9wQAIdQCAQD3BAAh1QIBAPMEACHWAgEA9wQAIdcCAQD3BAAh2QIBAPcEACHaAkAA-AQAIdsCQACDBQAhFA0AAIoFACAPAACLBQAgEAAAjAUAIBEAAI0FACATAACPBQAgsAIBAAAAAbkCAAAA0AICwAJAAAAAAcwCAQAAAAHOAgAAAM4CAtECAAAA0QIC0gIBAAAAAdMCAQAAAAHUAgEAAAAB1QIBAAAAAdYCAQAAAAHXAgEAAAAB2QIBAAAAAdoCQAAAAAHbAkAAAAABFA8AAIsFACAQAACMBQAgEQAAjQUAIBIAAI4FACATAACPBQAgsAIBAAAAAbkCAAAA0AICwAJAAAAAAcwCAQAAAAHOAgAAAM4CAtECAAAA0QIC0gIBAAAAAdQCAQAAAAHVAgEAAAAB1gIBAAAAAdcCAQAAAAHYAgEAAAAB2QIBAAAAAdoCQAAAAAHbAkAAAAABAgAAACAAIDEAAIYGACADAAAAIAAgMQAAhgYAIDIAAIUGACABKgAAxAgAMAIAAAAgACAqAACFBgAgAgAAAM4FACAqAACEBgAgD7ACAQDzBAAhuQIAAIEF0AIiwAJAAPgEACHMAgEA8wQAIc4CAACABc4CItECAACCBdECItICAQDzBAAh1AIBAPcEACHVAgEA8wQAIdYCAQD3BAAh1wIBAPcEACHYAgEA9wQAIdkCAQD3BAAh2gJAAPgEACHbAkAAgwUAIRQPAACFBQAgEAAAhgUAIBEAAIcFACASAACIBQAgEwAAiQUAILACAQDzBAAhuQIAAIEF0AIiwAJAAPgEACHMAgEA8wQAIc4CAACABc4CItECAACCBdECItICAQDzBAAh1AIBAPcEACHVAgEA8wQAIdYCAQD3BAAh1wIBAPcEACHYAgEA9wQAIdkCAQD3BAAh2gJAAPgEACHbAkAAgwUAIRQPAACLBQAgEAAAjAUAIBEAAI0FACASAACOBQAgEwAAjwUAILACAQAAAAG5AgAAANACAsACQAAAAAHMAgEAAAABzgIAAADOAgLRAgAAANECAtICAQAAAAHUAgEAAAAB1QIBAAAAAdYCAQAAAAHXAgEAAAAB2AIBAAAAAdkCAQAAAAHaAkAAAAAB2wJAAAAAAQsUAADcBQAgFQAA3QUAILACAQAAAAHAAkAAAAABzAIBAAAAAdoCQAAAAAH6AoAAAAAB-wIgAAAAAfwCAgAAAAH9AgEAAAAB_gIIAAAAAQIAAADrAQAgMQAAhwYAIAMAAAAcACAxAACHBgAgMgAAiwYAIA0AAAAcACAUAADEBQAgFQAAxQUAICoAAIsGACCwAgEA8wQAIcACQAD4BAAhzAIBAPMEACHaAkAA-AQAIfoCgAAAAAH7AiAAnwUAIfwCAgCVBQAh_QIBAPcEACH-AggAwgUAIQsUAADEBQAgFQAAxQUAILACAQDzBAAhwAJAAPgEACHMAgEA8wQAIdoCQAD4BAAh-gKAAAAAAfsCIACfBQAh_AICAJUFACH9AgEA9wQAIf4CCADCBQAhCLACAQAAAAHAAkAAAAAB2gJAAAAAAfACAQAAAAGIAwEAAAABiQMCAAAAAYoDAQAAAAGLAwEAAAABAgAAANMBACAxAACMBgAgAwAAABoAIDEAAIwGACAyAACQBgAgCgAAABoAICoAAJAGACCwAgEA8wQAIcACQAD4BAAh2gJAAPgEACHwAgEA8wQAIYgDAQDzBAAhiQMCAJUFACGKAwEA8wQAIYsDAQDzBAAhCLACAQDzBAAhwAJAAPgEACHaAkAA-AQAIfACAQDzBAAhiAMBAPMEACGJAwIAlQUAIYoDAQDzBAAhiwMBAPMEACEDMQAAwggAIK4DAADDCAAgtAMAAAEAIAMxAADACAAgrgMAAMEIACC0AwAABQAgAzEAAL4IACCuAwAAvwgAILQDAABxACADMQAAjAYAIK4DAACNBgAgtAMAANMBACADMQAAhwYAIK4DAACIBgAgtAMAAOsBACAEMQAA_gUAMK4DAAD_BQAwsAMAAIEGACC0AwAAygUAMAQxAAD1BQAwrgMAAPYFADCwAwAA-AUAILQDAADKBQAwAAAAAbEDAAAAmQMCBzEAALUIACAyAAC8CAAgrgMAALYIACCvAwAAuwgAILIDAAAHACCzAwAABwAgtAMAAAEAIAcxAACzCAAgMgAAuQgAIK4DAAC0CAAgrwMAALgIACCyAwAACQAgswMAAAkAILQDAABxACALMQAAnwYAMDIAAKQGADCuAwAAoAYAMK8DAAChBgAwsAMAAKIGACCxAwAAowYAMLIDAACjBgAwswMAAKMGADC0AwAAowYAMLUDAAClBgAwtgMAAKYGADATCAAAkwYAIAsAAJEGACAOAACUBgAgDwAAlQYAIBUAAJcGACAXAACWBgAgsAIBAAAAAbECAQAAAAG5AgAAAJMDAsACQAAAAAHaAkAAAAAB8AIBAAAAAf4CCAAAAAGMAwEAAAABjQMBAAAAAY8DAAAAjwMCkAMIAAAAAZEDgAAAAAGTAwEAAAABAgAAABYAIDEAAKoGACADAAAAFgAgMQAAqgYAIDIAAKkGACABKgAAtwgAMBgIAADTBAAgCwAAmAQAIAwAAN8EACAOAADgBAAgDwAA2wQAIBUAAK0EACAXAACtBAAgrQIAANwEADCuAgAAFAAQrwIAANwEADCwAgEAAAABsQIBAMwEACG5AgAA3gSTAyLAAkAAlgQAIdoCQACWBAAh8AIBAMwEACH-AggAqwQAIYwDAQAAAAGNAwEAzAQAIY8DAADdBI8DIpADCACrBAAhkQMAAKkEACCTAwEAlAQAIZQDAQDMBAAhAgAAABYAICoAAKkGACACAAAApwYAICoAAKgGACARrQIAAKYGADCuAgAApwYAEK8CAACmBgAwsAIBAJQEACGxAgEAzAQAIbkCAADeBJMDIsACQACWBAAh2gJAAJYEACHwAgEAzAQAIf4CCACrBAAhjAMBAJQEACGNAwEAzAQAIY8DAADdBI8DIpADCACrBAAhkQMAAKkEACCTAwEAlAQAIZQDAQDMBAAhEa0CAACmBgAwrgIAAKcGABCvAgAApgYAMLACAQCUBAAhsQIBAMwEACG5AgAA3gSTAyLAAkAAlgQAIdoCQACWBAAh8AIBAMwEACH-AggAqwQAIYwDAQCUBAAhjQMBAMwEACGPAwAA3QSPAyKQAwgAqwQAIZEDAACpBAAgkwMBAJQEACGUAwEAzAQAIQ2wAgEA8wQAIbECAQD3BAAhuQIAAO0FkwMiwAJAAPgEACHaAkAA-AQAIfACAQD3BAAh_gIIAMIFACGMAwEA8wQAIY0DAQD3BAAhjwMAAOwFjwMikAMIAMIFACGRA4AAAAABkwMBAPMEACETCAAA8AUAIAsAAO4FACAOAADxBQAgDwAA8gUAIBUAAPQFACAXAADzBQAgsAIBAPMEACGxAgEA9wQAIbkCAADtBZMDIsACQAD4BAAh2gJAAPgEACHwAgEA9wQAIf4CCADCBQAhjAMBAPMEACGNAwEA9wQAIY8DAADsBY8DIpADCADCBQAhkQOAAAAAAZMDAQDzBAAhEwgAAJMGACALAACRBgAgDgAAlAYAIA8AAJUGACAVAACXBgAgFwAAlgYAILACAQAAAAGxAgEAAAABuQIAAACTAwLAAkAAAAAB2gJAAAAAAfACAQAAAAH-AggAAAABjAMBAAAAAY0DAQAAAAGPAwAAAI8DApADCAAAAAGRA4AAAAABkwMBAAAAAQMxAAC1CAAgrgMAALYIACC0AwAAAQAgAzEAALMIACCuAwAAtAgAILQDAABxACAEMQAAnwYAMK4DAACgBgAwsAMAAKIGACC0AwAAowYAMAAAAAUxAACrCAAgMgAAsQgAIK4DAACsCAAgrwMAALAIACC0AwAAcQAgBTEAAKkIACAyAACuCAAgrgMAAKoIACCvAwAArQgAILQDAAABACADMQAAqwgAIK4DAACsCAAgtAMAAHEAIAMxAACpCAAgrgMAAKoIACC0AwAAAQAgAAAABTEAAJ8IACAyAACnCAAgrgMAAKAIACCvAwAApggAILQDAAABACALMQAA6wYAMDIAAPAGADCuAwAA7AYAMK8DAADtBgAwsAMAAO4GACCxAwAA7wYAMLIDAADvBgAwswMAAO8GADC0AwAA7wYAMLUDAADxBgAwtgMAAPIGADALMQAA3wYAMDIAAOQGADCuAwAA4AYAMK8DAADhBgAwsAMAAOIGACCxAwAA4wYAMLIDAADjBgAwswMAAOMGADC0AwAA4wYAMLUDAADlBgAwtgMAAOYGADALMQAA0wYAMDIAANgGADCuAwAA1AYAMK8DAADVBgAwsAMAANYGACCxAwAA1wYAMLIDAADXBgAwswMAANcGADC0AwAA1wYAMLUDAADZBgAwtgMAANoGADALMQAAygYAMDIAAM4GADCuAwAAywYAMK8DAADMBgAwsAMAAM0GACCxAwAAowYAMLIDAACjBgAwswMAAKMGADC0AwAAowYAMLUDAADPBgAwtgMAAKYGADALMQAAvgYAMDIAAMMGADCuAwAAvwYAMK8DAADABgAwsAMAAMEGACCxAwAAwgYAMLIDAADCBgAwswMAAMIGADC0AwAAwgYAMLUDAADEBgAwtgMAAMUGADAOGQAA_AQAILACAQAAAAGyAgEAAAABswIBAAAAAbQCAQAAAAG1AgEAAAABtwIAAAC3AgK5AgAAALkCArsCAAAAuwICvAIBAAAAAb0CAQAAAAG-AgEAAAABvwIBAAAAAcACQAAAAAECAAAAMAAgMQAAyQYAIAMAAAAwACAxAADJBgAgMgAAyAYAIAEqAAClCAAwEwgAANMEACAZAADUBAAgrQIAAM8EADCuAgAALgAQrwIAAM8EADCwAgEAAAABsQIBAMwEACGyAgEAzAQAIbMCAQCUBAAhtAIBAJQEACG1AgEAlAQAIbcCAADQBLcCIrkCAADRBLkCIrsCAADSBLsCIrwCAQCUBAAhvQIBAMwEACG-AgEAzAQAIb8CAQDMBAAhwAJAAJYEACECAAAAMAAgKgAAyAYAIAIAAADGBgAgKgAAxwYAIBGtAgAAxQYAMK4CAADGBgAQrwIAAMUGADCwAgEAlAQAIbECAQDMBAAhsgIBAMwEACGzAgEAlAQAIbQCAQCUBAAhtQIBAJQEACG3AgAA0AS3AiK5AgAA0QS5AiK7AgAA0gS7AiK8AgEAlAQAIb0CAQDMBAAhvgIBAMwEACG_AgEAzAQAIcACQACWBAAhEa0CAADFBgAwrgIAAMYGABCvAgAAxQYAMLACAQCUBAAhsQIBAMwEACGyAgEAzAQAIbMCAQCUBAAhtAIBAJQEACG1AgEAlAQAIbcCAADQBLcCIrkCAADRBLkCIrsCAADSBLsCIrwCAQCUBAAhvQIBAMwEACG-AgEAzAQAIb8CAQDMBAAhwAJAAJYEACENsAIBAPMEACGyAgEA9wQAIbMCAQDzBAAhtAIBAPMEACG1AgEA8wQAIbcCAAD0BLcCIrkCAAD1BLkCIrsCAAD2BLsCIrwCAQDzBAAhvQIBAPcEACG-AgEA9wQAIb8CAQD3BAAhwAJAAPgEACEOGQAA-gQAILACAQDzBAAhsgIBAPcEACGzAgEA8wQAIbQCAQDzBAAhtQIBAPMEACG3AgAA9AS3AiK5AgAA9QS5AiK7AgAA9gS7AiK8AgEA8wQAIb0CAQD3BAAhvgIBAPcEACG_AgEA9wQAIcACQAD4BAAhDhkAAPwEACCwAgEAAAABsgIBAAAAAbMCAQAAAAG0AgEAAAABtQIBAAAAAbcCAAAAtwICuQIAAAC5AgK7AgAAALsCArwCAQAAAAG9AgEAAAABvgIBAAAAAb8CAQAAAAHAAkAAAAABEwsAAJEGACAMAACSBgAgDgAAlAYAIA8AAJUGACAVAACXBgAgFwAAlgYAILACAQAAAAG5AgAAAJMDAsACQAAAAAHaAkAAAAAB8AIBAAAAAf4CCAAAAAGMAwEAAAABjQMBAAAAAY8DAAAAjwMCkAMIAAAAAZEDgAAAAAGTAwEAAAABlAMBAAAAAQIAAAAWACAxAADSBgAgAwAAABYAIDEAANIGACAyAADRBgAgASoAAKQIADACAAAAFgAgKgAA0QYAIAIAAACnBgAgKgAA0AYAIA2wAgEA8wQAIbkCAADtBZMDIsACQAD4BAAh2gJAAPgEACHwAgEA9wQAIf4CCADCBQAhjAMBAPMEACGNAwEA9wQAIY8DAADsBY8DIpADCADCBQAhkQOAAAAAAZMDAQDzBAAhlAMBAPcEACETCwAA7gUAIAwAAO8FACAOAADxBQAgDwAA8gUAIBUAAPQFACAXAADzBQAgsAIBAPMEACG5AgAA7QWTAyLAAkAA-AQAIdoCQAD4BAAh8AIBAPcEACH-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-gcAMK4DAAD3BwAwrwMAAPgHADCwAwAA-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-AgEA9wQAIb8CAQD3BAAhwAJAAPgEACEOCAAA-QQAILACAQDzBAAhsQIBAPcEACGzAgEA8wQAIbQCAQDzBAAhtQIBAPMEACG3AgAA9AS3AiK5AgAA9QS5AiK7AgAA9gS7AiK8AgEA8wQAIb0CAQD3BAAhvgIBAPcEACG_AgEA9wQAIcACQAD4BAAhDggAAPsEACCwAgEAAAABsQIBAAAAAbMCAQAAAAG0AgEAAAABtQIBAAAAAbcCAAAAtwICuQIAAAC5AgK7AgAAALsCArwCAQAAAAG9AgEAAAABvgIBAAAAAb8CAQAAAAHAAkAAAAABB7ACAQAAAAG5AgAAAN8CAsACQAAAAAHdAgIAAAAB3wIBAAAAAeECAAAA4QIC4wIAAADjAgICAAAATgAgMQAAuwcAIAMAAABOACAxAAC7BwAgMgAAugcAIAEqAACbCAAwDAYAAJgEACCtAgAAxwQAMK4CAABMABCvAgAAxwQAMLACAQAAAAG5AgAAyATfAiLAAkAAlgQAIdwCAQCUBAAh3QICAKoEACHfAgEAlAQAIeECAADJBOECIuMCAADKBOMCIgIAAABOACAqAAC6BwAgAgAAALgHACAqAAC5BwAgC60CAAC3BwAwrgIAALgHABCvAgAAtwcAMLACAQCUBAAhuQIAAMgE3wIiwAJAAJYEACHcAgEAlAQAId0CAgCqBAAh3wIBAJQEACHhAgAAyQThAiLjAgAAygTjAiILrQIAALcHADCuAgAAuAcAEK8CAAC3BwAwsAIBAJQEACG5AgAAyATfAiLAAkAAlgQAIdwCAQCUBAAh3QICAKoEACHfAgEAlAQAIeECAADJBOECIuMCAADKBOMCIgewAgEA8wQAIbkCAACWBd8CIsACQAD4BAAh3QICAJUFACHfAgEA8wQAIeECAACXBeECIuMCAACYBeMCIgewAgEA8wQAIbkCAACWBd8CIsACQAD4BAAh3QICAJUFACHfAgEA8wQAIeECAACXBeECIuMCAACYBeMCIgewAgEAAAABuQIAAADfAgLAAkAAAAAB3QICAAAAAd8CAQAAAAHhAgAAAOECAuMCAAAA4wICCLACAQAAAAG5AgAAAOcCAsACQAAAAAHaAkAAAAAB5AIBAAAAAeUCAQAAAAHnAkAAAAAB6AIgAAAAAQIAAAD1AgAgMQAAvAcAIAMAAABKACAxAAC8BwAgMgAAwAcAIAoAAABKACAqAADABwAgsAIBAPMEACG5AgAAngXnAiLAAkAA-AQAIdoCQAD4BAAh5AIBAPMEACHlAgEA8wQAIecCQAD4BAAh6AIgAJ8FACEIsAIBAPMEACG5AgAAngXnAiLAAkAA-AQAIdoCQAD4BAAh5AIBAPMEACHlAgEA8wQAIecCQAD4BAAh6AIgAJ8FACEGBQAAswYAILACAQAAAAGxAgEAAAABwAJAAAAAAdoCQAAAAAGdAyAAAAABAgAAAA0AIDEAAMEHACADAAAACwAgMQAAwQcAIDIAAMUHACAIAAAACwAgBQAAsQYAICoAAMUHACCwAgEA8wQAIbECAQDzBAAhwAJAAPgEACHaAkAA-AQAIZ0DIACfBQAhBgUAALEGACCwAgEA8wQAIbECAQDzBAAhwAJAAPgEACHaAkAA-AQAIZ0DIACfBQAhCQcAAPgGACAJAAD5BgAgCgAA-gYAIBgAAPsGACAaAAD8BgAgsAIBAAAAAcACQAAAAAHaAkAAAAAB8AIBAAAAAQIAAABxACAxAADGBwAgAwAAAAkAIDEAAMYHACAyAADKBwAgCwAAAAkAIAcAALkGACAJAAC6BgAgCgAAuwYAIBgAALwGACAaAAC9BgAgKgAAygcAILACAQDzBAAhwAJAAPgEACHaAkAA-AQAIfACAQDzBAAhCQcAALkGACAJAAC6BgAgCgAAuwYAIBgAALwGACAaAAC9BgAgsAIBAPMEACHAAkAA-AQAIdoCQAD4BAAh8AIBAPMEACEJsAIBAAAAAcACQAAAAAHaAkAAAAAB6QIBAAAAAeoCAQAAAAHrAgEAAAAB7AJAAAAAAe0CQAAAAAHuAiAAAAABAgAAAEYAIDEAANYHACADAAAARgAgMQAA1gcAIDIAANUHACABKgAAmggAMA4GAACYBAAgrQIAAMsEADCuAgAARAAQrwIAAMsEADCwAgEAAAABwAJAAJYEACHaAkAAlgQAIdwCAQCUBAAh6QIBAAAAAeoCAQDMBAAh6wIBAMwEACHsAkAAlgQAIe0CQACWBAAh7gIgAJcEACECAAAARgAgKgAA1QcAIAIAAADTBwAgKgAA1AcAIA2tAgAA0gcAMK4CAADTBwAQrwIAANIHADCwAgEAlAQAIcACQACWBAAh2gJAAJYEACHcAgEAlAQAIekCAQCUBAAh6gIBAMwEACHrAgEAzAQAIewCQACWBAAh7QJAAJYEACHuAiAAlwQAIQ2tAgAA0gcAMK4CAADTBwAQrwIAANIHADCwAgEAlAQAIcACQACWBAAh2gJAAJYEACHcAgEAlAQAIekCAQCUBAAh6gIBAMwEACHrAgEAzAQAIewCQACWBAAh7QJAAJYEACHuAiAAlwQAIQmwAgEA8wQAIcACQAD4BAAh2gJAAPgEACHpAgEA8wQAIeoCAQD3BAAh6wIBAPcEACHsAkAA-AQAIe0CQAD4BAAh7gIgAJ8FACEJsAIBAPMEACHAAkAA-AQAIdoCQAD4BAAh6QIBAPMEACHqAgEA9wQAIesCAQD3BAAh7AJAAPgEACHtAkAA-AQAIe4CIACfBQAhCbACAQAAAAHAAkAAAAAB2gJAAAAAAekCAQAAAAHqAgEAAAAB6wIBAAAAAewCQAAAAAHtAkAAAAAB7gIgAAAAAQawAgEAAAABwAJAAAAAAdoCQAAAAAHyAiAAAAAB8wIgAAAAAfQCIAAAAAECAAAAsQIAIDEAANcHACADAAAAQgAgMQAA1wcAIDIAANsHACAIAAAAQgAgKgAA2wcAILACAQDzBAAhwAJAAPgEACHaAkAA-AQAIfICIACfBQAh8wIgAJ8FACH0AiAAnwUAIQawAgEA8wQAIcACQAD4BAAh2gJAAPgEACHyAiAAnwUAIfMCIACfBQAh9AIgAJ8FACEGsAIBAAAAAcACQAAAAAHaAkAAAAAB8gIgAAAAAfMCIAAAAAH0AiAAAAABAgAAAJkCACAxAADcBwAgAwAAAEAAIDEAANwHACAyAADgBwAgCAAAAEAAICoAAOAHACCwAgEA8wQAIcACQAD4BAAh2gJAAPgEACHyAiAAnwUAIfMCIACfBQAh9AIgAJ8FACEGsAIBAPMEACHAAkAA-AQAIdoCQAD4BAAh8gIgAJ8FACHzAiAAnwUAIfQCIACfBQAhCLACAQAAAAHAAkAAAAABzgIAAAD5AgLaAkAAAAAB9QIBAAAAAfYCAQAAAAH3AgEAAAAB-QIgAAAAAQIAAAA-ACAxAADsBwAgAwAAAD4AIDEAAOwHACAyAADrBwAgASoAAJkIADANBgAAmAQAIK0CAADNBAAwrgIAADwAEK8CAADNBAAwsAIBAAAAAcACQACWBAAhzgIAAM4E-QIi2gJAAJYEACHcAgEAlAQAIfUCAQCUBAAh9gIBAJQEACH3AgEAzAQAIfkCIACXBAAhAgAAAD4AICoAAOsHACACAAAA6QcAICoAAOoHACAMrQIAAOgHADCuAgAA6QcAEK8CAADoBwAwsAIBAJQEACHAAkAAlgQAIc4CAADOBPkCItoCQACWBAAh3AIBAJQEACH1AgEAlAQAIfYCAQCUBAAh9wIBAMwEACH5AiAAlwQAIQytAgAA6AcAMK4CAADpBwAQrwIAAOgHADCwAgEAlAQAIcACQACWBAAhzgIAAM4E-QIi2gJAAJYEACHcAgEAlAQAIfUCAQCUBAAh9gIBAJQEACH3AgEAzAQAIfkCIACXBAAhCLACAQDzBAAhwAJAAPgEACHOAgAAugX5AiLaAkAA-AQAIfUCAQDzBAAh9gIBAPMEACH3AgEA9wQAIfkCIACfBQAhCLACAQDzBAAhwAJAAPgEACHOAgAAugX5AiLaAkAA-AQAIfUCAQDzBAAh9gIBAPMEACH3AgEA9wQAIfkCIACfBQAhCLACAQAAAAHAAkAAAAABzgIAAAD5AgLaAkAAAAAB9QIBAAAAAfYCAQAAAAH3AgEAAAAB-QIgAAAAARMIAACTBgAgDAAAkgYAIA4AAJQGACAPAACVBgAgFQAAlwYAIBcAAJYGACCwAgEAAAABsQIBAAAAAbkCAAAAkwMCwAJAAAAAAdoCQAAAAAHwAgEAAAAB_gIIAAAAAYwDAQAAAAGNAwEAAAABjwMAAACPAwKQAwgAAAABkQOAAAAAAZQDAQAAAAECAAAAFgAgMQAA9QcAIAMAAAAWACAxAAD1BwAgMgAA9AcAIAEqAACYCAAwAgAAABYAICoAAPQHACACAAAApwYAICoAAPMHACANsAIBAPMEACGxAgEA9wQAIbkCAADtBZMDIsACQAD4BAAh2gJAAPgEACHwAgEA9wQAIf4CCADCBQAhjAMBAPMEACGNAwEA9wQAIY8DAADsBY8DIpADCADCBQAhkQOAAAAAAZQDAQD3BAAhEwgAAPAFACAMAADvBQAgDgAA8QUAIA8AAPIFACAVAAD0BQAgFwAA8wUAILACAQDzBAAhsQIBAPcEACG5AgAA7QWTAyLAAkAA-AQAIdoCQAD4BAAh8AIBAPcEACH-AggAwgUAIYwDAQDzBAAhjQMBAPcEACGPAwAA7AWPAyKQAwgAwgUAIZEDgAAAAAGUAwEA9wQAIRMIAACTBgAgDAAAkgYAIA4AAJQGACAPAACVBgAgFQAAlwYAIBcAAJYGACCwAgEAAAABsQIBAAAAAbkCAAAAkwMCwAJAAAAAAdoCQAAAAAHwAgEAAAAB_gIIAAAAAYwDAQAAAAGNAwEAAAABjwMAAACPAwKQAwgAAAABkQOAAAAAAZQDAQAAAAEMCAAArAYAIBgAAK0GACCwAgEAAAABsQIBAAAAAcACQAAAAAHaAkAAAAABlQMBAAAAAZYDAQAAAAGXAwEAAAABmQMAAACZAwKaAwEAAAABmwMBAAAAAQIAAAAFACAxAAD-BwAgAwAAAAUAIDEAAP4HACAyAAD9BwAgASoAAJcIADACAAAABQAgKgAA_QcAIAIAAADbBgAgKgAA_AcAIAqwAgEA8wQAIbECAQD3BAAhwAJAAPgEACHaAkAA-AQAIZUDAQDzBAAhlgMBAPMEACGXAwEA8wQAIZkDAACbBpkDIpoDAQDzBAAhmwMBAPMEACEMCAAAnQYAIBgAAJ4GACCwAgEA8wQAIbECAQD3BAAhwAJAAPgEACHaAkAA-AQAIZUDAQDzBAAhlgMBAPMEACGXAwEA8wQAIZkDAACbBpkDIpoDAQDzBAAhmwMBAPMEACEMCAAArAYAIBgAAK0GACCwAgEAAAABsQIBAAAAAcACQAAAAAHaAkAAAAABlQMBAAAAAZYDAQAAAAGXAwEAAAABmQMAAACZAwKaAwEAAAABmwMBAAAAAQQxAAD2BwAwrgMAAPcHADCwAwAA-QcAILQDAADXBgAwBDEAAO0HADCuAwAA7gcAMLADAADwBwAgtAMAAKMGADAEMQAA4QcAMK4DAADiBwAwsAMAAOQHACC0AwAA5QcAMAMxAADcBwAgrgMAAN0HACC0AwAAmQIAIAMxAADXBwAgrgMAANgHACC0AwAAsQIAIAQxAADLBwAwrgMAAMwHADCwAwAAzgcAILQDAADPBwAwAzEAAMYHACCuAwAAxwcAILQDAABxACADMQAAwQcAIK4DAADCBwAgtAMAAA0AIAMxAAC8BwAgrgMAAL0HACC0AwAA9QIAIAQxAACwBwAwrgMAALEHADCwAwAAswcAILQDAAC0BwAwBDEAAKcHADCuAwAAqAcAMLADAACqBwAgtAMAAMIGADAEMQAAngcAMK4DAACfBwAwsAMAAKEHACC0AwAAygUAMAQxAACVBwAwrgMAAJYHADCwAwAAmAcAILQDAADKBQAwAAEGAACiBQAgAQYAAKIFACAABgQAAKIFACAHAAD9BgAgCQAA_gYAIAoAAP8GACAYAACABwAgGgAAgQcAIAIFAACQCAAgBgAAogUAIAEGAACiBQAgAAQNAADeBQAgFAAA3wUAIBUAAN8FACD9AgAA7wQAIAUDAACiBQAgCAAAkAgAIBgAAIAHACCxAgAA7wQAIJwDAADvBAAgAQ0AAN4FACAKsAIBAAAAAbECAQAAAAHAAkAAAAAB2gJAAAAAAZUDAQAAAAGWAwEAAAABlwMBAAAAAZkDAAAAmQMCmgMBAAAAAZsDAQAAAAENsAIBAAAAAbECAQAAAAG5AgAAAJMDAsACQAAAAAHaAkAAAAAB8AIBAAAAAf4CCAAAAAGMAwEAAAABjQMBAAAAAY8DAAAAjwMCkAMIAAAAAZEDgAAAAAGUAwEAAAABCLACAQAAAAHAAkAAAAABzgIAAAD5AgLaAkAAAAAB9QIBAAAAAfYCAQAAAAH3AgEAAAAB-QIgAAAAAQmwAgEAAAABwAJAAAAAAdoCQAAAAAHpAgEAAAAB6gIBAAAAAesCAQAAAAHsAkAAAAAB7QJAAAAAAe4CIAAAAAEHsAIBAAAAAbkCAAAA3wICwAJAAAAAAd0CAgAAAAHfAgEAAAAB4QIAAADhAgLjAgAAAOMCAg2wAgEAAAABsQIBAAAAAbMCAQAAAAG0AgEAAAABtQIBAAAAAbcCAAAAtwICuQIAAAC5AgK7AgAAALsCArwCAQAAAAG9AgEAAAABvgIBAAAAAb8CAQAAAAHAAkAAAAABD7ACAQAAAAG5AgAAANACAsACQAAAAAHMAgEAAAABzgIAAADOAgLRAgAAANECAtICAQAAAAHTAgEAAAAB1AIBAAAAAdYCAQAAAAHXAgEAAAAB2AIBAAAAAdkCAQAAAAHaAkAAAAAB2wJAAAAAAQ-wAgEAAAABuQIAAADQAgLAAkAAAAABzAIBAAAAAc4CAAAAzgIC0QIAAADRAgLSAgEAAAAB0wIBAAAAAdQCAQAAAAHVAgEAAAAB1wIBAAAAAdgCAQAAAAHZAgEAAAAB2gJAAAAAAdsCQAAAAAEdCgAA_wcAIBgAAIAIACAaAACJCAAgGwAAgQgAIBwAAIIIACAdAACDCAAgHgAAhAgAICAAAIYIACAhAACHCAAgIgAAiAgAICMAAIoIACAkAACLCAAgsAIBAAAAAcACQAAAAAHaAkAAAAAB4QIAAADhAgKaAwEAAAABnwMBAAAAAaADAQAAAAGhAwEAAAABogMBAAAAAaQDAAAApAMCpQMgAAAAAaYDAgAAAAGnAwIAAAABqAMBAAAAAakDIAAAAAGqAwEAAAABqwNAAAAAAQIAAAABACAxAACfCAAgBbACAQAAAAHAAkAAAAAB2gJAAAAAAdwCAQAAAAGdAyAAAAABBrACAQAAAAHAAkAAAAAB2gJAAAAAAewCQAAAAAHwAgEAAAAB8QIBAAAAAQqwAgEAAAABwAJAAAAAAdoCQAAAAAGVAwEAAAABlgMBAAAAAZcDAQAAAAGZAwAAAJkDApoDAQAAAAGbAwEAAAABnAMBAAAAAQ2wAgEAAAABuQIAAACTAwLAAkAAAAAB2gJAAAAAAfACAQAAAAH-AggAAAABjAMBAAAAAY0DAQAAAAGPAwAAAI8DApADCAAAAAGRA4AAAAABkwMBAAAAAZQDAQAAAAENsAIBAAAAAbICAQAAAAGzAgEAAAABtAIBAAAAAbUCAQAAAAG3AgAAALcCArkCAAAAuQICuwIAAAC7AgK8AgEAAAABvQIBAAAAAb4CAQAAAAG_AgEAAAABwAJAAAAAAQMAAAAHACAxAACfCAAgMgAAqAgAIB8AAAAHACAKAACIBwAgGAAAiQcAIBoAAJIHACAbAACKBwAgHAAAiwcAIB0AAIwHACAeAACNBwAgIAAAjwcAICEAAJAHACAiAACRBwAgIwAAkwcAICQAAJQHACAqAACoCAAgsAIBAPMEACHAAkAA-AQAIdoCQAD4BAAh4QIAAJcF4QIimgMBAPMEACGfAwEA8wQAIaADAQD3BAAhoQMBAPcEACGiAwEA9wQAIaQDAACHB6QDIqUDIACfBQAhpgMCAJUFACGnAwIAlQUAIagDAQD3BAAhqQMgAJ8FACGqAwEA9wQAIasDQACDBQAhHQoAAIgHACAYAACJBwAgGgAAkgcAIBsAAIoHACAcAACLBwAgHQAAjAcAIB4AAI0HACAgAACPBwAgIQAAkAcAICIAAJEHACAjAACTBwAgJAAAlAcAILACAQDzBAAhwAJAAPgEACHaAkAA-AQAIeECAACXBeECIpoDAQDzBAAhnwMBAPMEACGgAwEA9wQAIaEDAQD3BAAhogMBAPcEACGkAwAAhwekAyKlAyAAnwUAIaYDAgCVBQAhpwMCAJUFACGoAwEA9wQAIakDIACfBQAhqgMBAPcEACGrA0AAgwUAIR0KAAD_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-AQAIfACAQD3BAAh_gIIAMIFACGMAwEA8wQAIY0DAQD3BAAhjwMAAOwFjwMikAMIAMIFACGRA4AAAAABkwMBAPMEACGUAwEA9wQAIRQIAADwBQAgCwAA7gUAIAwAAO8FACAPAADyBQAgFQAA9AUAIBcAAPMFACCwAgEA8wQAIbECAQD3BAAhuQIAAO0FkwMiwAJAAPgEACHaAkAA-AQAIfACAQD3BAAh_gIIAMIFACGMAwEA8wQAIY0DAQD3BAAhjwMAAOwFjwMikAMIAMIFACGRA4AAAAABkwMBAPMEACGUAwEA9wQAIRQIAACTBgAgCwAAkQYAIAwAAJIGACAOAACUBgAgFQAAlwYAIBcAAJYGACCwAgEAAAABsQIBAAAAAbkCAAAAkwMCwAJAAAAAAdoCQAAAAAHwAgEAAAAB_gIIAAAAAYwDAQAAAAGNAwEAAAABjwMAAACPAwKQAwgAAAABkQOAAAAAAZMDAQAAAAGUAwEAAAABAgAAABYAIDEAANQIACAPsAIBAAAAAbkCAAAA0AICwAJAAAAAAcwCAQAAAAHOAgAAAM4CAtECAAAA0QIC0gIBAAAAAdMCAQAAAAHVAgEAAAAB1gIBAAAAAdcCAQAAAAHYAgEAAAAB2QIBAAAAAdoCQAAAAAHbAkAAAAABD7ACAQAAAAG5AgAAANACAsACQAAAAAHMAgEAAAABzgIAAADOAgLRAgAAANECAtICAQAAAAHTAgEAAAAB1AIBAAAAAdUCAQAAAAHWAgEAAAAB1wIBAAAAAdgCAQAAAAHaAkAAAAAB2wJAAAAAAQMAAAAUACAxAADUCAAgMgAA2ggAIBYAAAAUACAIAADwBQAgCwAA7gUAIAwAAO8FACAOAADxBQAgFQAA9AUAIBcAAPMFACAqAADaCAAgsAIBAPMEACGxAgEA9wQAIbkCAADtBZMDIsACQAD4BAAh2gJAAPgEACHwAgEA9wQAIf4CCADCBQAhjAMBAPMEACGNAwEA9wQAIY8DAADsBY8DIpADCADCBQAhkQOAAAAAAZMDAQDzBAAhlAMBAPcEACEUCAAA8AUAIAsAAO4FACAMAADvBQAgDgAA8QUAIBUAAPQFACAXAADzBQAgsAIBAPMEACGxAgEA9wQAIbkCAADtBZMDIsACQAD4BAAh2gJAAPgEACHwAgEA9wQAIf4CCADCBQAhjAMBAPMEACGNAwEA9wQAIY8DAADsBY8DIpADCADCBQAhkQOAAAAAAZMDAQDzBAAhlAMBAPcEACEdCgAA_wcAIBgAAIAIACAaAACJCAAgHAAAgggAIB0AAIMIACAeAACECAAgHwAAhQgAICAAAIYIACAhAACHCAAgIgAAiAgAICMAAIoIACAkAACLCAAgsAIBAAAAAcACQAAAAAHaAkAAAAAB4QIAAADhAgKaAwEAAAABnwMBAAAAAaADAQAAAAGhAwEAAAABogMBAAAAAaQDAAAApAMCpQMgAAAAAaYDAgAAAAGnAwIAAAABqAMBAAAAAakDIAAAAAGqAwEAAAABqwNAAAAAAQIAAAABACAxAADbCAAgAwAAAAcAIDEAANsIACAyAADfCAAgHwAAAAcAIAoAAIgHACAYAACJBwAgGgAAkgcAIBwAAIsHACAdAACMBwAgHgAAjQcAIB8AAI4HACAgAACPBwAgIQAAkAcAICIAAJEHACAjAACTBwAgJAAAlAcAICoAAN8IACCwAgEA8wQAIcACQAD4BAAh2gJAAPgEACHhAgAAlwXhAiKaAwEA8wQAIZ8DAQDzBAAhoAMBAPcEACGhAwEA9wQAIaIDAQD3BAAhpAMAAIcHpAMipQMgAJ8FACGmAwIAlQUAIacDAgCVBQAhqAMBAPcEACGpAyAAnwUAIaoDAQD3BAAhqwNAAIMFACEdCgAAiAcAIBgAAIkHACAaAACSBwAgHAAAiwcAIB0AAIwHACAeAACNBwAgHwAAjgcAICAAAI8HACAhAACQBwAgIgAAkQcAICMAAJMHACAkAACUBwAgsAIBAPMEACHAAkAA-AQAIdoCQAD4BAAh4QIAAJcF4QIimgMBAPMEACGfAwEA8wQAIaADAQD3BAAhoQMBAPcEACGiAwEA9wQAIaQDAACHB6QDIqUDIACfBQAhpgMCAJUFACGnAwIAlQUAIagDAQD3BAAhqQMgAJ8FACGqAwEA9wQAIasDQACDBQAhHQoAAP8HACAYAACACAAgGgAAiQgAIBsAAIEIACAdAACDCAAgHgAAhAgAIB8AAIUIACAgAACGCAAgIQAAhwgAICIAAIgIACAjAACKCAAgJAAAiwgAILACAQAAAAHAAkAAAAAB2gJAAAAAAeECAAAA4QICmgMBAAAAAZ8DAQAAAAGgAwEAAAABoQMBAAAAAaIDAQAAAAGkAwAAAKQDAqUDIAAAAAGmAwIAAAABpwMCAAAAAagDAQAAAAGpAyAAAAABqgMBAAAAAasDQAAAAAECAAAAAQAgMQAA4AgAIAMAAAAHACAxAADgCAAgMgAA5AgAIB8AAAAHACAKAACIBwAgGAAAiQcAIBoAAJIHACAbAACKBwAgHQAAjAcAIB4AAI0HACAfAACOBwAgIAAAjwcAICEAAJAHACAiAACRBwAgIwAAkwcAICQAAJQHACAqAADkCAAgsAIBAPMEACHAAkAA-AQAIdoCQAD4BAAh4QIAAJcF4QIimgMBAPMEACGfAwEA8wQAIaADAQD3BAAhoQMBAPcEACGiAwEA9wQAIaQDAACHB6QDIqUDIACfBQAhpgMCAJUFACGnAwIAlQUAIagDAQD3BAAhqQMgAJ8FACGqAwEA9wQAIasDQACDBQAhHQoAAIgHACAYAACJBwAgGgAAkgcAIBsAAIoHACAdAACMBwAgHgAAjQcAIB8AAI4HACAgAACPBwAgIQAAkAcAICIAAJEHACAjAACTBwAgJAAAlAcAILACAQDzBAAhwAJAAPgEACHaAkAA-AQAIeECAACXBeECIpoDAQDzBAAhnwMBAPMEACGgAwEA9wQAIaEDAQD3BAAhogMBAPcEACGkAwAAhwekAyKlAyAAnwUAIaYDAgCVBQAhpwMCAJUFACGoAwEA9wQAIakDIACfBQAhqgMBAPcEACGrA0AAgwUAIR0KAAD_BwAgGAAAgAgAIBoAAIkIACAbAACBCAAgHAAAgggAIB4AAIQIACAfAACFCAAgIAAAhggAICEAAIcIACAiAACICAAgIwAAiggAICQAAIsIACCwAgEAAAABwAJAAAAAAdoCQAAAAAHhAgAAAOECApoDAQAAAAGfAwEAAAABoAMBAAAAAaEDAQAAAAGiAwEAAAABpAMAAACkAwKlAyAAAAABpgMCAAAAAacDAgAAAAGoAwEAAAABqQMgAAAAAaoDAQAAAAGrA0AAAAABAgAAAAEAIDEAAOUIACADAAAABwAgMQAA5QgAIDIAAOkIACAfAAAABwAgCgAAiAcAIBgAAIkHACAaAACSBwAgGwAAigcAIBwAAIsHACAeAACNBwAgHwAAjgcAICAAAI8HACAhAACQBwAgIgAAkQcAICMAAJMHACAkAACUBwAgKgAA6QgAILACAQDzBAAhwAJAAPgEACHaAkAA-AQAIeECAACXBeECIpoDAQDzBAAhnwMBAPMEACGgAwEA9wQAIaEDAQD3BAAhogMBAPcEACGkAwAAhwekAyKlAyAAnwUAIaYDAgCVBQAhpwMCAJUFACGoAwEA9wQAIakDIACfBQAhqgMBAPcEACGrA0AAgwUAIR0KAACIBwAgGAAAiQcAIBoAAJIHACAbAACKBwAgHAAAiwcAIB4AAI0HACAfAACOBwAgIAAAjwcAICEAAJAHACAiAACRBwAgIwAAkwcAICQAAJQHACCwAgEA8wQAIcACQAD4BAAh2gJAAPgEACHhAgAAlwXhAiKaAwEA8wQAIZ8DAQDzBAAhoAMBAPcEACGhAwEA9wQAIaIDAQD3BAAhpAMAAIcHpAMipQMgAJ8FACGmAwIAlQUAIacDAgCVBQAhqAMBAPcEACGpAyAAnwUAIaoDAQD3BAAhqwNAAIMFACEKBAAA9wYAIAcAAPgGACAKAAD6BgAgGAAA-wYAIBoAAPwGACCwAgEAAAABwAJAAAAAAdoCQAAAAAHwAgEAAAABngMBAAAAAQIAAABxACAxAADqCAAgAwAAAAkAIDEAAOoIACAyAADuCAAgDAAAAAkAIAQAALgGACAHAAC5BgAgCgAAuwYAIBgAALwGACAaAAC9BgAgKgAA7ggAILACAQDzBAAhwAJAAPgEACHaAkAA-AQAIfACAQDzBAAhngMBAPMEACEKBAAAuAYAIAcAALkGACAKAAC7BgAgGAAAvAYAIBoAAL0GACCwAgEA8wQAIcACQAD4BAAh2gJAAPgEACHwAgEA8wQAIZ4DAQDzBAAhHQoAAP8HACAYAACACAAgGgAAiQgAIBsAAIEIACAcAACCCAAgHQAAgwgAIB8AAIUIACAgAACGCAAgIQAAhwgAICIAAIgIACAjAACKCAAgJAAAiwgAILACAQAAAAHAAkAAAAAB2gJAAAAAAeECAAAA4QICmgMBAAAAAZ8DAQAAAAGgAwEAAAABoQMBAAAAAaIDAQAAAAGkAwAAAKQDAqUDIAAAAAGmAwIAAAABpwMCAAAAAagDAQAAAAGpAyAAAAABqgMBAAAAAasDQAAAAAECAAAAAQAgMQAA7wgAIAMAAAAHACAxAADvCAAgMgAA8wgAIB8AAAAHACAKAACIBwAgGAAAiQcAIBoAAJIHACAbAACKBwAgHAAAiwcAIB0AAIwHACAfAACOBwAgIAAAjwcAICEAAJAHACAiAACRBwAgIwAAkwcAICQAAJQHACAqAADzCAAgsAIBAPMEACHAAkAA-AQAIdoCQAD4BAAh4QIAAJcF4QIimgMBAPMEACGfAwEA8wQAIaADAQD3BAAhoQMBAPcEACGiAwEA9wQAIaQDAACHB6QDIqUDIACfBQAhpgMCAJUFACGnAwIAlQUAIagDAQD3BAAhqQMgAJ8FACGqAwEA9wQAIasDQACDBQAhHQoAAIgHACAYAACJBwAgGgAAkgcAIBsAAIoHACAcAACLBwAgHQAAjAcAIB8AAI4HACAgAACPBwAgIQAAkAcAICIAAJEHACAjAACTBwAgJAAAlAcAILACAQDzBAAhwAJAAPgEACHaAkAA-AQAIeECAACXBeECIpoDAQDzBAAhnwMBAPMEACGgAwEA9wQAIaEDAQD3BAAhogMBAPcEACGkAwAAhwekAyKlAyAAnwUAIaYDAgCVBQAhpwMCAJUFACGoAwEA9wQAIakDIACfBQAhqgMBAPcEACGrA0AAgwUAIR0KAAD_BwAgGAAAgAgAIBoAAIkIACAbAACBCAAgHAAAgggAIB0AAIMIACAeAACECAAgHwAAhQgAICAAAIYIACAiAACICAAgIwAAiggAICQAAIsIACCwAgEAAAABwAJAAAAAAdoCQAAAAAHhAgAAAOECApoDAQAAAAGfAwEAAAABoAMBAAAAAaEDAQAAAAGiAwEAAAABpAMAAACkAwKlAyAAAAABpgMCAAAAAacDAgAAAAGoAwEAAAABqQMgAAAAAaoDAQAAAAGrA0AAAAABAgAAAAEAIDEAAPQIACADAAAABwAgMQAA9AgAIDIAAPgIACAfAAAABwAgCgAAiAcAIBgAAIkHACAaAACSBwAgGwAAigcAIBwAAIsHACAdAACMBwAgHgAAjQcAIB8AAI4HACAgAACPBwAgIgAAkQcAICMAAJMHACAkAACUBwAgKgAA-AgAILACAQDzBAAhwAJAAPgEACHaAkAA-AQAIeECAACXBeECIpoDAQDzBAAhnwMBAPMEACGgAwEA9wQAIaEDAQD3BAAhogMBAPcEACGkAwAAhwekAyKlAyAAnwUAIaYDAgCVBQAhpwMCAJUFACGoAwEA9wQAIakDIACfBQAhqgMBAPcEACGrA0AAgwUAIR0KAACIBwAgGAAAiQcAIBoAAJIHACAbAACKBwAgHAAAiwcAIB0AAIwHACAeAACNBwAgHwAAjgcAICAAAI8HACAiAACRBwAgIwAAkwcAICQAAJQHACCwAgEA8wQAIcACQAD4BAAh2gJAAPgEACHhAgAAlwXhAiKaAwEA8wQAIZ8DAQDzBAAhoAMBAPcEACGhAwEA9wQAIaIDAQD3BAAhpAMAAIcHpAMipQMgAJ8FACGmAwIAlQUAIacDAgCVBQAhqAMBAPcEACGpAyAAnwUAIaoDAQD3BAAhqwNAAIMFACEdCgAA_wcAIBgAAIAIACAaAACJCAAgGwAAgQgAIBwAAIIIACAdAACDCAAgHgAAhAgAIB8AAIUIACAgAACGCAAgIQAAhwgAICMAAIoIACAkAACLCAAgsAIBAAAAAcACQAAAAAHaAkAAAAAB4QIAAADhAgKaAwEAAAABnwMBAAAAAaADAQAAAAGhAwEAAAABogMBAAAAAaQDAAAApAMCpQMgAAAAAaYDAgAAAAGnAwIAAAABqAMBAAAAAakDIAAAAAGqAwEAAAABqwNAAAAAAQIAAAABACAxAAD5CAAgAwAAAAcAIDEAAPkIACAyAAD9CAAgHwAAAAcAIAoAAIgHACAYAACJBwAgGgAAkgcAIBsAAIoHACAcAACLBwAgHQAAjAcAIB4AAI0HACAfAACOBwAgIAAAjwcAICEAAJAHACAjAACTBwAgJAAAlAcAICoAAP0IACCwAgEA8wQAIcACQAD4BAAh2gJAAPgEACHhAgAAlwXhAiKaAwEA8wQAIZ8DAQDzBAAhoAMBAPcEACGhAwEA9wQAIaIDAQD3BAAhpAMAAIcHpAMipQMgAJ8FACGmAwIAlQUAIacDAgCVBQAhqAMBAPcEACGpAyAAnwUAIaoDAQD3BAAhqwNAAIMFACEdCgAAiAcAIBgAAIkHACAaAACSBwAgGwAAigcAIBwAAIsHACAdAACMBwAgHgAAjQcAIB8AAI4HACAgAACPBwAgIQAAkAcAICMAAJMHACAkAACUBwAgsAIBAPMEACHAAkAA-AQAIdoCQAD4BAAh4QIAAJcF4QIimgMBAPMEACGfAwEA8wQAIaADAQD3BAAhoQMBAPcEACGiAwEA9wQAIaQDAACHB6QDIqUDIACfBQAhpgMCAJUFACGnAwIAlQUAIagDAQD3BAAhqQMgAJ8FACGqAwEA9wQAIasDQACDBQAhDA0AANsFACAUAADcBQAgsAIBAAAAAcACQAAAAAHMAgEAAAAB0wIBAAAAAdoCQAAAAAH6AoAAAAAB-wIgAAAAAfwCAgAAAAH9AgEAAAAB_gIIAAAAAQIAAADrAQAgMQAA_ggAIBQIAACTBgAgCwAAkQYAIAwAAJIGACAOAACUBgAgDwAAlQYAIBcAAJYGACCwAgEAAAABsQIBAAAAAbkCAAAAkwMCwAJAAAAAAdoCQAAAAAHwAgEAAAAB_gIIAAAAAYwDAQAAAAGNAwEAAAABjwMAAACPAwKQAwgAAAABkQOAAAAAAZMDAQAAAAGUAwEAAAABAgAAABYAIDEAAIAJACAdCgAA_wcAIBgAAIAIACAaAACJCAAgGwAAgQgAIBwAAIIIACAdAACDCAAgHgAAhAgAIB8AAIUIACAgAACGCAAgIQAAhwgAICIAAIgIACAjAACKCAAgsAIBAAAAAcACQAAAAAHaAkAAAAAB4QIAAADhAgKaAwEAAAABnwMBAAAAAaADAQAAAAGhAwEAAAABogMBAAAAAaQDAAAApAMCpQMgAAAAAaYDAgAAAAGnAwIAAAABqAMBAAAAAakDIAAAAAGqAwEAAAABqwNAAAAAAQIAAAABACAxAACCCQAgHQoAAP8HACAYAACACAAgGgAAiQgAIBsAAIEIACAcAACCCAAgHQAAgwgAIB4AAIQIACAfAACFCAAgIAAAhggAICEAAIcIACAiAACICAAgJAAAiwgAILACAQAAAAHAAkAAAAAB2gJAAAAAAeECAAAA4QICmgMBAAAAAZ8DAQAAAAGgAwEAAAABoQMBAAAAAaIDAQAAAAGkAwAAAKQDAqUDIAAAAAGmAwIAAAABpwMCAAAAAagDAQAAAAGpAyAAAAABqgMBAAAAAasDQAAAAAECAAAAAQAgMQAAhAkAIAwNAADbBQAgFQAA3QUAILACAQAAAAHAAkAAAAABzAIBAAAAAdMCAQAAAAHaAkAAAAAB-gKAAAAAAfsCIAAAAAH8AgIAAAAB_QIBAAAAAf4CCAAAAAECAAAA6wEAIDEAAIYJACAUCAAAkwYAIAsAAJEGACAMAACSBgAgDgAAlAYAIA8AAJUGACAVAACXBgAgsAIBAAAAAbECAQAAAAG5AgAAAJMDAsACQAAAAAHaAkAAAAAB8AIBAAAAAf4CCAAAAAGMAwEAAAABjQMBAAAAAY8DAAAAjwMCkAMIAAAAAZEDgAAAAAGTAwEAAAABlAMBAAAAAQIAAAAWACAxAACICQAgAwAAABwAIDEAAP4IACAyAACMCQAgDgAAABwAIA0AAMMFACAUAADEBQAgKgAAjAkAILACAQDzBAAhwAJAAPgEACHMAgEA8wQAIdMCAQDzBAAh2gJAAPgEACH6AoAAAAAB-wIgAJ8FACH8AgIAlQUAIf0CAQD3BAAh_gIIAMIFACEMDQAAwwUAIBQAAMQFACCwAgEA8wQAIcACQAD4BAAhzAIBAPMEACHTAgEA8wQAIdoCQAD4BAAh-gKAAAAAAfsCIACfBQAh_AICAJUFACH9AgEA9wQAIf4CCADCBQAhAwAAABQAIDEAAIAJACAyAACPCQAgFgAAABQAIAgAAPAFACALAADuBQAgDAAA7wUAIA4AAPEFACAPAADyBQAgFwAA8wUAICoAAI8JACCwAgEA8wQAIbECAQD3BAAhuQIAAO0FkwMiwAJAAPgEACHaAkAA-AQAIfACAQD3BAAh_gIIAMIFACGMAwEA8wQAIY0DAQD3BAAhjwMAAOwFjwMikAMIAMIFACGRA4AAAAABkwMBAPMEACGUAwEA9wQAIRQIAADwBQAgCwAA7gUAIAwAAO8FACAOAADxBQAgDwAA8gUAIBcAAPMFACCwAgEA8wQAIbECAQD3BAAhuQIAAO0FkwMiwAJAAPgEACHaAkAA-AQAIfACAQD3BAAh_gIIAMIFACGMAwEA8wQAIY0DAQD3BAAhjwMAAOwFjwMikAMIAMIFACGRA4AAAAABkwMBAPMEACGUAwEA9wQAIQMAAAAHACAxAACCCQAgMgAAkgkAIB8AAAAHACAKAACIBwAgGAAAiQcAIBoAAJIHACAbAACKBwAgHAAAiwcAIB0AAIwHACAeAACNBwAgHwAAjgcAICAAAI8HACAhAACQBwAgIgAAkQcAICMAAJMHACAqAACSCQAgsAIBAPMEACHAAkAA-AQAIdoCQAD4BAAh4QIAAJcF4QIimgMBAPMEACGfAwEA8wQAIaADAQD3BAAhoQMBAPcEACGiAwEA9wQAIaQDAACHB6QDIqUDIACfBQAhpgMCAJUFACGnAwIAlQUAIagDAQD3BAAhqQMgAJ8FACGqAwEA9wQAIasDQACDBQAhHQoAAIgHACAYAACJBwAgGgAAkgcAIBsAAIoHACAcAACLBwAgHQAAjAcAIB4AAI0HACAfAACOBwAgIAAAjwcAICEAAJAHACAiAACRBwAgIwAAkwcAILACAQDzBAAhwAJAAPgEACHaAkAA-AQAIeECAACXBeECIpoDAQDzBAAhnwMBAPMEACGgAwEA9wQAIaEDAQD3BAAhogMBAPcEACGkAwAAhwekAyKlAyAAnwUAIaYDAgCVBQAhpwMCAJUFACGoAwEA9wQAIakDIACfBQAhqgMBAPcEACGrA0AAgwUAIQMAAAAHACAxAACECQAgMgAAlQkAIB8AAAAHACAKAACIBwAgGAAAiQcAIBoAAJIHACAbAACKBwAgHAAAiwcAIB0AAIwHACAeAACNBwAgHwAAjgcAICAAAI8HACAhAACQBwAgIgAAkQcAICQAAJQHACAqAACVCQAgsAIBAPMEACHAAkAA-AQAIdoCQAD4BAAh4QIAAJcF4QIimgMBAPMEACGfAwEA8wQAIaADAQD3BAAhoQMBAPcEACGiAwEA9wQAIaQDAACHB6QDIqUDIACfBQAhpgMCAJUFACGnAwIAlQUAIagDAQD3BAAhqQMgAJ8FACGqAwEA9wQAIasDQACDBQAhHQoAAIgHACAYAACJBwAgGgAAkgcAIBsAAIoHACAcAACLBwAgHQAAjAcAIB4AAI0HACAfAACOBwAgIAAAjwcAICEAAJAHACAiAACRBwAgJAAAlAcAILACAQDzBAAhwAJAAPgEACHaAkAA-AQAIeECAACXBeECIpoDAQDzBAAhnwMBAPMEACGgAwEA9wQAIaEDAQD3BAAhogMBAPcEACGkAwAAhwekAyKlAyAAnwUAIaYDAgCVBQAhpwMCAJUFACGoAwEA9wQAIakDIACfBQAhqgMBAPcEACGrA0AAgwUAIQMAAAAcACAxAACGCQAgMgAAmAkAIA4AAAAcACANAADDBQAgFQAAxQUAICoAAJgJACCwAgEA8wQAIcACQAD4BAAhzAIBAPMEACHTAgEA8wQAIdoCQAD4BAAh-gKAAAAAAfsCIACfBQAh_AICAJUFACH9AgEA9wQAIf4CCADCBQAhDA0AAMMFACAVAADFBQAgsAIBAPMEACHAAkAA-AQAIcwCAQDzBAAh0wIBAPMEACHaAkAA-AQAIfoCgAAAAAH7AiAAnwUAIfwCAgCVBQAh_QIBAPcEACH-AggAwgUAIQMAAAAUACAxAACICQAgMgAAmwkAIBYAAAAUACAIAADwBQAgCwAA7gUAIAwAAO8FACAOAADxBQAgDwAA8gUAIBUAAPQFACAqAACbCQAgsAIBAPMEACGxAgEA9wQAIbkCAADtBZMDIsACQAD4BAAh2gJAAPgEACHwAgEA9wQAIf4CCADCBQAhjAMBAPMEACGNAwEA9wQAIY8DAADsBY8DIpADCADCBQAhkQOAAAAAAZMDAQDzBAAhlAMBAPcEACEUCAAA8AUAIAsAAO4FACAMAADvBQAgDgAA8QUAIA8AAPIFACAVAAD0BQAgsAIBAPMEACGxAgEA9wQAIbkCAADtBZMDIsACQAD4BAAh2gJAAPgEACHwAgEA9wQAIf4CCADCBQAhjAMBAPMEACGNAwEA9wQAIY8DAADsBY8DIpADCADCBQAhkQOAAAAAAZMDAQDzBAAhlAMBAPcEACEdCgAA_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-OAB_OQCAAToAgQEGDa0DBg-uAwgQAAERrwMBErADBhOxAwgGDbcDBg-4AwgQAAERuQMBEroDBhO7AwgDFgCGATkAhwE6AIgBAAAAAxYAhgE5AIcBOgCIAQIIzQMDGc4DAQII1AMDGdUDAQMWAI0BOQCOAToAjwEAAAADFgCNATkAjgE6AI8BJQIBJlsBJ10BKF4BKV8BK2EBLGMWLWQXLmYBL2gWMGkYM2oBNGsBNWwWO28ZPHAfPXIDPnMDP3UDQHYDQXcDQnkDQ3sWRHwgRX4DRoABFkeBASFIggEDSYMBA0qEARZLhwEiTIgBJk2JAQROigEET4sBBFCMAQRRjQEEUo8BBFORARZUkgEnVZQBBFaWARZXlwEoWJgBBFmZAQRamgEWW50BKVyeAS1dnwECXqABAl-hAQJgogECYaMBAmKlAQJjpwEWZKgBLmWsAQJmrgEWZ68BL2iyAQJpswECarQBFmu3ATBsuAE0bbkBBm66AQZvuwEGcLwBBnG9AQZyvwEGc8EBFnTCATV1xgEGdsgBFnfJATZ4zAEGec0BBnrOARZ70QE3fNIBPX3UAQd-1QEHf9cBB4AB2AEHgQHZAQeCAdsBB4MB3QEWhAHeAT6FAeABB4YB4gEWhwHjAT-IAeQBB4kB5QEHigHmARaLAekBQIwB6gFGjQHsAQiOAe0BCI8B7wEIkAHwAQiRAfEBCJIB8wEIkwH1ARaUAfYBR5UB-AEIlgH6ARaXAfsBSJgB_AEImQH9AQiaAf4BFpsBgQJJnAGCAk-dAYMCD54BhAIPnwGFAg-gAYYCD6EBhwIPogGJAg-jAYsCFqQBjAJQpQGOAg-mAZACFqcBkQJRqAGSAg-pAZMCD6oBlAIWqwGXAlKsAZgCVq0BmgIQrgGbAhCvAZ0CELABngIQsQGfAhCyAaECELMBowIWtAGkAle1AaYCELYBqAIWtwGpAli4AaoCELkBqwIQugGsAha7Aa8CWbwBsAJdvQGyAhG-AbMCEb8BtQIRwAG2AhHBAbcCEcIBuQIRwwG7AhbEAbwCXsUBvgIRxgHAAhbHAcECX8gBwgIRyQHDAhHKAcQCFssBxwJgzAHIAmTNAckCBc4BygIFzwHLAgXQAcwCBdEBzQIF0gHPAgXTAdECFtQB0gJl1QHUAgXWAdYCFtcB1wJm2AHYAgXZAdkCBdoB2gIW2wHdAmfcAd4Ca90B3wIS3gHgAhLfAeECEuAB4gIS4QHjAhLiAeUCEuMB5wIW5AHoAmzlAeoCEuYB7AIW5wHtAm3oAe4CEukB7wIS6gHwAhbrAfMCbuwB9AJy7QH2AhPuAfcCE-8B-QIT8AH6AhPxAfsCE_IB_QIT8wH_Ahb0AYADc_UBggMT9gGEAxb3AYUDdPgBhgMT-QGHAxP6AYgDFvsBiwN1_AGMA3n9AY0DFP4BjgMU_wGPAxSAApADFIECkQMUggKTAxSDApUDFoQClgN6hQKYAxSGApoDFocCmwN7iAKcAxSJAp0DFIoCngMWiwKhA3yMAqIDggGNAqMDCY4CpAMJjwKlAwmQAqYDCZECpwMJkgKpAwmTAqsDFpQCrAODAZUCswMJlgK1AxaXArYDhAGYArwDCZkCvQMJmgK-AxabAsEDhQGcAsIDiQGdAsMDDJ4CxAMMnwLFAwygAsYDDKECxwMMogLJAwyjAssDFqQCzAOKAaUC0AMMpgLSAxanAtMDiwGoAtYDDKkC1wMMqgLYAxarAtsDjAGsAtwDkAE" } async function decodeBase64AsWasm(wasmBase64: string): Promise { @@ -328,6 +328,16 @@ export interface PrismaClient< */ get payment(): Prisma.PaymentDelegate; + /** + * `prisma.ticket`: Exposes CRUD operations for the **Ticket** model. + * Example usage: + * ```ts + * // Fetch zero or more Tickets + * const tickets = await prisma.ticket.findMany() + * ``` + */ + get ticket(): Prisma.TicketDelegate; + /** * `prisma.auditLog`: Exposes CRUD operations for the **AuditLog** model. * Example usage: diff --git a/server/prisma/generated/client/internal/prismaNamespace.ts b/server/prisma/generated/client/internal/prismaNamespace.ts index e9e8d7d..6d09fbe 100644 --- a/server/prisma/generated/client/internal/prismaNamespace.ts +++ b/server/prisma/generated/client/internal/prismaNamespace.ts @@ -398,6 +398,7 @@ export const ModelName = { Session: 'Session', Subscription: 'Subscription', Payment: 'Payment', + Ticket: 'Ticket', AuditLog: 'AuditLog' } as const @@ -414,7 +415,7 @@ export type TypeMap + fields: Prisma.TicketFieldRefs + operations: { + findUnique: { + args: Prisma.TicketFindUniqueArgs + result: runtime.Types.Utils.PayloadToResult | null + } + findUniqueOrThrow: { + args: Prisma.TicketFindUniqueOrThrowArgs + result: runtime.Types.Utils.PayloadToResult + } + findFirst: { + args: Prisma.TicketFindFirstArgs + result: runtime.Types.Utils.PayloadToResult | null + } + findFirstOrThrow: { + args: Prisma.TicketFindFirstOrThrowArgs + result: runtime.Types.Utils.PayloadToResult + } + findMany: { + args: Prisma.TicketFindManyArgs + result: runtime.Types.Utils.PayloadToResult[] + } + create: { + args: Prisma.TicketCreateArgs + result: runtime.Types.Utils.PayloadToResult + } + createMany: { + args: Prisma.TicketCreateManyArgs + result: BatchPayload + } + createManyAndReturn: { + args: Prisma.TicketCreateManyAndReturnArgs + result: runtime.Types.Utils.PayloadToResult[] + } + delete: { + args: Prisma.TicketDeleteArgs + result: runtime.Types.Utils.PayloadToResult + } + update: { + args: Prisma.TicketUpdateArgs + result: runtime.Types.Utils.PayloadToResult + } + deleteMany: { + args: Prisma.TicketDeleteManyArgs + result: BatchPayload + } + updateMany: { + args: Prisma.TicketUpdateManyArgs + result: BatchPayload + } + updateManyAndReturn: { + args: Prisma.TicketUpdateManyAndReturnArgs + result: runtime.Types.Utils.PayloadToResult[] + } + upsert: { + args: Prisma.TicketUpsertArgs + result: runtime.Types.Utils.PayloadToResult + } + aggregate: { + args: Prisma.TicketAggregateArgs + result: runtime.Types.Utils.Optional + } + groupBy: { + args: Prisma.TicketGroupByArgs + result: runtime.Types.Utils.Optional[] + } + count: { + args: Prisma.TicketCountArgs + result: runtime.Types.Utils.Optional | number + } + } + } AuditLog: { payload: Prisma.$AuditLogPayload fields: Prisma.AuditLogFieldRefs @@ -1780,6 +1855,28 @@ export const PaymentScalarFieldEnum = { export type PaymentScalarFieldEnum = (typeof PaymentScalarFieldEnum)[keyof typeof PaymentScalarFieldEnum] +export const TicketScalarFieldEnum = { + id: 'id', + code: 'code', + type: 'type', + status: 'status', + priority: 'priority', + reason: 'reason', + scanId: 'scanId', + reportId: 'reportId', + submittedById: 'submittedById', + assignedToId: 'assignedToId', + resolutionNote: 'resolutionNote', + reanalysisScanId: 'reanalysisScanId', + reanalysisReportId: 'reanalysisReportId', + createdAt: 'createdAt', + updatedAt: 'updatedAt', + resolvedAt: 'resolvedAt' +} as const + +export type TicketScalarFieldEnum = (typeof TicketScalarFieldEnum)[keyof typeof TicketScalarFieldEnum] + + export const AuditLogScalarFieldEnum = { id: 'id', orgId: 'orgId', @@ -2049,6 +2146,48 @@ export type ListEnumPaymentModeFieldRefInput<$PrismaModel> = FieldRefInputType<$ +/** + * Reference to a field of type 'TicketType' + */ +export type EnumTicketTypeFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'TicketType'> + + + +/** + * Reference to a field of type 'TicketType[]' + */ +export type ListEnumTicketTypeFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'TicketType[]'> + + + +/** + * Reference to a field of type 'TicketStatus' + */ +export type EnumTicketStatusFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'TicketStatus'> + + + +/** + * Reference to a field of type 'TicketStatus[]' + */ +export type ListEnumTicketStatusFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'TicketStatus[]'> + + + +/** + * Reference to a field of type 'TicketPriority' + */ +export type EnumTicketPriorityFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'TicketPriority'> + + + +/** + * Reference to a field of type 'TicketPriority[]' + */ +export type ListEnumTicketPriorityFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'TicketPriority[]'> + + + /** * Reference to a field of type 'AuditCategory' */ @@ -2199,6 +2338,7 @@ export type GlobalOmitConfig = { session?: Prisma.SessionOmit subscription?: Prisma.SubscriptionOmit payment?: Prisma.PaymentOmit + ticket?: Prisma.TicketOmit auditLog?: Prisma.AuditLogOmit } diff --git a/server/prisma/generated/client/internal/prismaNamespaceBrowser.ts b/server/prisma/generated/client/internal/prismaNamespaceBrowser.ts index 55c6279..c44de20 100644 --- a/server/prisma/generated/client/internal/prismaNamespaceBrowser.ts +++ b/server/prisma/generated/client/internal/prismaNamespaceBrowser.ts @@ -65,6 +65,7 @@ export const ModelName = { Session: 'Session', Subscription: 'Subscription', Payment: 'Payment', + Ticket: 'Ticket', AuditLog: 'AuditLog' } as const @@ -297,6 +298,28 @@ export const PaymentScalarFieldEnum = { export type PaymentScalarFieldEnum = (typeof PaymentScalarFieldEnum)[keyof typeof PaymentScalarFieldEnum] +export const TicketScalarFieldEnum = { + id: 'id', + code: 'code', + type: 'type', + status: 'status', + priority: 'priority', + reason: 'reason', + scanId: 'scanId', + reportId: 'reportId', + submittedById: 'submittedById', + assignedToId: 'assignedToId', + resolutionNote: 'resolutionNote', + reanalysisScanId: 'reanalysisScanId', + reanalysisReportId: 'reanalysisReportId', + createdAt: 'createdAt', + updatedAt: 'updatedAt', + resolvedAt: 'resolvedAt' +} as const + +export type TicketScalarFieldEnum = (typeof TicketScalarFieldEnum)[keyof typeof TicketScalarFieldEnum] + + export const AuditLogScalarFieldEnum = { id: 'id', orgId: 'orgId', diff --git a/server/prisma/generated/client/models.ts b/server/prisma/generated/client/models.ts index 8e414f6..5ad8267 100644 --- a/server/prisma/generated/client/models.ts +++ b/server/prisma/generated/client/models.ts @@ -22,5 +22,6 @@ export type * from './models/ApiKey.js' export type * from './models/Session.js' export type * from './models/Subscription.js' export type * from './models/Payment.js' +export type * from './models/Ticket.js' export type * from './models/AuditLog.js' export type * from './commonInputTypes.js' \ No newline at end of file diff --git a/server/prisma/generated/client/models/AuditLog.ts b/server/prisma/generated/client/models/AuditLog.ts index 28a3f1c..74a3425 100644 --- a/server/prisma/generated/client/models/AuditLog.ts +++ b/server/prisma/generated/client/models/AuditLog.ts @@ -203,7 +203,7 @@ export type AuditLogGroupByArgs | string - orgId?: Prisma.StringFilter<"AuditLog"> | string + orgId?: Prisma.StringNullableFilter<"AuditLog"> | string | null actorId?: Prisma.StringNullableFilter<"AuditLog"> | string | null actorName?: Prisma.StringFilter<"AuditLog"> | string actorEmail?: Prisma.StringFilter<"AuditLog"> | string @@ -254,13 +254,13 @@ export type AuditLogWhereInput = { ip?: Prisma.StringNullableFilter<"AuditLog"> | string | null userAgent?: Prisma.StringNullableFilter<"AuditLog"> | string | null createdAt?: Prisma.DateTimeFilter<"AuditLog"> | Date | string - organization?: Prisma.XOR + organization?: Prisma.XOR | null actor?: Prisma.XOR | null } export type AuditLogOrderByWithRelationInput = { id?: Prisma.SortOrder - orgId?: Prisma.SortOrder + orgId?: Prisma.SortOrderInput | Prisma.SortOrder actorId?: Prisma.SortOrderInput | Prisma.SortOrder actorName?: Prisma.SortOrder actorEmail?: Prisma.SortOrder @@ -282,7 +282,7 @@ export type AuditLogWhereUniqueInput = Prisma.AtLeast<{ AND?: Prisma.AuditLogWhereInput | Prisma.AuditLogWhereInput[] OR?: Prisma.AuditLogWhereInput[] NOT?: Prisma.AuditLogWhereInput | Prisma.AuditLogWhereInput[] - orgId?: Prisma.StringFilter<"AuditLog"> | string + orgId?: Prisma.StringNullableFilter<"AuditLog"> | string | null actorId?: Prisma.StringNullableFilter<"AuditLog"> | string | null actorName?: Prisma.StringFilter<"AuditLog"> | string actorEmail?: Prisma.StringFilter<"AuditLog"> | string @@ -295,13 +295,13 @@ export type AuditLogWhereUniqueInput = Prisma.AtLeast<{ ip?: Prisma.StringNullableFilter<"AuditLog"> | string | null userAgent?: Prisma.StringNullableFilter<"AuditLog"> | string | null createdAt?: Prisma.DateTimeFilter<"AuditLog"> | Date | string - organization?: Prisma.XOR + organization?: Prisma.XOR | null actor?: Prisma.XOR | null }, "id"> export type AuditLogOrderByWithAggregationInput = { id?: Prisma.SortOrder - orgId?: Prisma.SortOrder + orgId?: Prisma.SortOrderInput | Prisma.SortOrder actorId?: Prisma.SortOrderInput | Prisma.SortOrder actorName?: Prisma.SortOrder actorEmail?: Prisma.SortOrder @@ -324,7 +324,7 @@ export type AuditLogScalarWhereWithAggregatesInput = { OR?: Prisma.AuditLogScalarWhereWithAggregatesInput[] NOT?: Prisma.AuditLogScalarWhereWithAggregatesInput | Prisma.AuditLogScalarWhereWithAggregatesInput[] id?: Prisma.StringWithAggregatesFilter<"AuditLog"> | string - orgId?: Prisma.StringWithAggregatesFilter<"AuditLog"> | string + orgId?: Prisma.StringNullableWithAggregatesFilter<"AuditLog"> | string | null actorId?: Prisma.StringNullableWithAggregatesFilter<"AuditLog"> | string | null actorName?: Prisma.StringWithAggregatesFilter<"AuditLog"> | string actorEmail?: Prisma.StringWithAggregatesFilter<"AuditLog"> | string @@ -352,13 +352,13 @@ export type AuditLogCreateInput = { ip?: string | null userAgent?: string | null createdAt?: Date | string - organization: Prisma.OrganizationCreateNestedOneWithoutAuditLogsInput + organization?: Prisma.OrganizationCreateNestedOneWithoutAuditLogsInput actor?: Prisma.UserCreateNestedOneWithoutAuditLogsInput } export type AuditLogUncheckedCreateInput = { id?: string - orgId: string + orgId?: string | null actorId?: string | null actorName: string actorEmail: string @@ -386,13 +386,13 @@ export type AuditLogUpdateInput = { ip?: Prisma.NullableStringFieldUpdateOperationsInput | string | null userAgent?: Prisma.NullableStringFieldUpdateOperationsInput | string | null createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string - organization?: Prisma.OrganizationUpdateOneRequiredWithoutAuditLogsNestedInput + organization?: Prisma.OrganizationUpdateOneWithoutAuditLogsNestedInput actor?: Prisma.UserUpdateOneWithoutAuditLogsNestedInput } export type AuditLogUncheckedUpdateInput = { id?: Prisma.StringFieldUpdateOperationsInput | string - orgId?: Prisma.StringFieldUpdateOperationsInput | string + orgId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null actorId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null actorName?: Prisma.StringFieldUpdateOperationsInput | string actorEmail?: Prisma.StringFieldUpdateOperationsInput | string @@ -409,7 +409,7 @@ export type AuditLogUncheckedUpdateInput = { export type AuditLogCreateManyInput = { id?: string - orgId: string + orgId?: string | null actorId?: string | null actorName: string actorEmail: string @@ -441,7 +441,7 @@ export type AuditLogUpdateManyMutationInput = { export type AuditLogUncheckedUpdateManyInput = { id?: Prisma.StringFieldUpdateOperationsInput | string - orgId?: Prisma.StringFieldUpdateOperationsInput | string + orgId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null actorId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null actorName?: Prisma.StringFieldUpdateOperationsInput | string actorEmail?: Prisma.StringFieldUpdateOperationsInput | string @@ -626,12 +626,12 @@ export type AuditLogCreateWithoutActorInput = { ip?: string | null userAgent?: string | null createdAt?: Date | string - organization: Prisma.OrganizationCreateNestedOneWithoutAuditLogsInput + organization?: Prisma.OrganizationCreateNestedOneWithoutAuditLogsInput } export type AuditLogUncheckedCreateWithoutActorInput = { id?: string - orgId: string + orgId?: string | null actorName: string actorEmail: string action: string @@ -676,7 +676,7 @@ export type AuditLogScalarWhereInput = { OR?: Prisma.AuditLogScalarWhereInput[] NOT?: Prisma.AuditLogScalarWhereInput | Prisma.AuditLogScalarWhereInput[] id?: Prisma.StringFilter<"AuditLog"> | string - orgId?: Prisma.StringFilter<"AuditLog"> | string + orgId?: Prisma.StringNullableFilter<"AuditLog"> | string | null actorId?: Prisma.StringNullableFilter<"AuditLog"> | string | null actorName?: Prisma.StringFilter<"AuditLog"> | string actorEmail?: Prisma.StringFilter<"AuditLog"> | string @@ -751,7 +751,7 @@ export type AuditLogUpdateManyWithWhereWithoutOrganizationInput = { export type AuditLogCreateManyActorInput = { id?: string - orgId: string + orgId?: string | null actorName: string actorEmail: string action: string @@ -778,12 +778,12 @@ export type AuditLogUpdateWithoutActorInput = { ip?: Prisma.NullableStringFieldUpdateOperationsInput | string | null userAgent?: Prisma.NullableStringFieldUpdateOperationsInput | string | null createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string - organization?: Prisma.OrganizationUpdateOneRequiredWithoutAuditLogsNestedInput + organization?: Prisma.OrganizationUpdateOneWithoutAuditLogsNestedInput } export type AuditLogUncheckedUpdateWithoutActorInput = { id?: Prisma.StringFieldUpdateOperationsInput | string - orgId?: Prisma.StringFieldUpdateOperationsInput | string + orgId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null actorName?: Prisma.StringFieldUpdateOperationsInput | string actorEmail?: Prisma.StringFieldUpdateOperationsInput | string action?: Prisma.StringFieldUpdateOperationsInput | string @@ -799,7 +799,7 @@ export type AuditLogUncheckedUpdateWithoutActorInput = { export type AuditLogUncheckedUpdateManyWithoutActorInput = { id?: Prisma.StringFieldUpdateOperationsInput | string - orgId?: Prisma.StringFieldUpdateOperationsInput | string + orgId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null actorName?: Prisma.StringFieldUpdateOperationsInput | string actorEmail?: Prisma.StringFieldUpdateOperationsInput | string action?: Prisma.StringFieldUpdateOperationsInput | string @@ -894,7 +894,7 @@ export type AuditLogSelect + organization?: boolean | Prisma.AuditLog$organizationArgs actor?: boolean | Prisma.AuditLog$actorArgs }, ExtArgs["result"]["auditLog"]> @@ -913,7 +913,7 @@ export type AuditLogSelectCreateManyAndReturn + organization?: boolean | Prisma.AuditLog$organizationArgs actor?: boolean | Prisma.AuditLog$actorArgs }, ExtArgs["result"]["auditLog"]> @@ -932,7 +932,7 @@ export type AuditLogSelectUpdateManyAndReturn + organization?: boolean | Prisma.AuditLog$organizationArgs actor?: boolean | Prisma.AuditLog$actorArgs }, ExtArgs["result"]["auditLog"]> @@ -955,27 +955,27 @@ export type AuditLogSelectScalar = { export type AuditLogOmit = runtime.Types.Extensions.GetOmit<"id" | "orgId" | "actorId" | "actorName" | "actorEmail" | "action" | "category" | "status" | "severity" | "target" | "targetId" | "ip" | "userAgent" | "createdAt", ExtArgs["result"]["auditLog"]> export type AuditLogInclude = { - organization?: boolean | Prisma.OrganizationDefaultArgs + organization?: boolean | Prisma.AuditLog$organizationArgs actor?: boolean | Prisma.AuditLog$actorArgs } export type AuditLogIncludeCreateManyAndReturn = { - organization?: boolean | Prisma.OrganizationDefaultArgs + organization?: boolean | Prisma.AuditLog$organizationArgs actor?: boolean | Prisma.AuditLog$actorArgs } export type AuditLogIncludeUpdateManyAndReturn = { - organization?: boolean | Prisma.OrganizationDefaultArgs + organization?: boolean | Prisma.AuditLog$organizationArgs actor?: boolean | Prisma.AuditLog$actorArgs } export type $AuditLogPayload = { name: "AuditLog" objects: { - organization: Prisma.$OrganizationPayload + organization: Prisma.$OrganizationPayload | null actor: Prisma.$UserPayload | null } scalars: runtime.Types.Extensions.GetPayloadResult<{ id: string - orgId: string + orgId: string | null actorId: string | null actorName: string actorEmail: string @@ -1382,7 +1382,7 @@ readonly fields: AuditLogFieldRefs; */ export interface Prisma__AuditLogClient extends Prisma.PrismaPromise { readonly [Symbol.toStringTag]: "PrismaPromise" - organization = {}>(args?: Prisma.Subset>): Prisma.Prisma__OrganizationClient, T, "findUniqueOrThrow", GlobalOmitOptions> | Null, Null, ExtArgs, GlobalOmitOptions> + organization = {}>(args?: Prisma.Subset>): Prisma.Prisma__OrganizationClient, T, "findUniqueOrThrow", GlobalOmitOptions> | null, null, ExtArgs, GlobalOmitOptions> actor = {}>(args?: Prisma.Subset>): Prisma.Prisma__UserClient, T, "findUniqueOrThrow", GlobalOmitOptions> | null, null, ExtArgs, GlobalOmitOptions> /** * Attaches callbacks for the resolution and/or rejection of the Promise. @@ -1827,6 +1827,25 @@ export type AuditLogDeleteManyArgs = { + /** + * Select specific fields to fetch from the Organization + */ + select?: Prisma.OrganizationSelect | null + /** + * Omit specific fields from the Organization + */ + omit?: Prisma.OrganizationOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.OrganizationInclude | null + where?: Prisma.OrganizationWhereInput +} + /** * AuditLog.actor */ diff --git a/server/prisma/generated/client/models/Organization.ts b/server/prisma/generated/client/models/Organization.ts index 6b67e20..a2056db 100644 --- a/server/prisma/generated/client/models/Organization.ts +++ b/server/prisma/generated/client/models/Organization.ts @@ -450,10 +450,12 @@ export type OrganizationCreateNestedOneWithoutAuditLogsInput = { connect?: Prisma.OrganizationWhereUniqueInput } -export type OrganizationUpdateOneRequiredWithoutAuditLogsNestedInput = { +export type OrganizationUpdateOneWithoutAuditLogsNestedInput = { create?: Prisma.XOR connectOrCreate?: Prisma.OrganizationCreateOrConnectWithoutAuditLogsInput upsert?: Prisma.OrganizationUpsertWithoutAuditLogsInput + disconnect?: Prisma.OrganizationWhereInput | boolean + delete?: Prisma.OrganizationWhereInput | boolean connect?: Prisma.OrganizationWhereUniqueInput update?: Prisma.XOR, Prisma.OrganizationUncheckedUpdateWithoutAuditLogsInput> } diff --git a/server/prisma/generated/client/models/Report.ts b/server/prisma/generated/client/models/Report.ts index c957914..7f52397 100644 --- a/server/prisma/generated/client/models/Report.ts +++ b/server/prisma/generated/client/models/Report.ts @@ -257,6 +257,8 @@ export type ReportWhereInput = { createdAt?: Prisma.DateTimeFilter<"Report"> | Date | string updatedAt?: Prisma.DateTimeFilter<"Report"> | Date | string scan?: Prisma.XOR + ticketsForReport?: Prisma.TicketListRelationFilter + ticketsAsReanalysis?: Prisma.TicketListRelationFilter } export type ReportOrderByWithRelationInput = { @@ -271,6 +273,8 @@ export type ReportOrderByWithRelationInput = { createdAt?: Prisma.SortOrder updatedAt?: Prisma.SortOrder scan?: Prisma.ScanOrderByWithRelationInput + ticketsForReport?: Prisma.TicketOrderByRelationAggregateInput + ticketsAsReanalysis?: Prisma.TicketOrderByRelationAggregateInput } export type ReportWhereUniqueInput = Prisma.AtLeast<{ @@ -288,6 +292,8 @@ export type ReportWhereUniqueInput = Prisma.AtLeast<{ createdAt?: Prisma.DateTimeFilter<"Report"> | Date | string updatedAt?: Prisma.DateTimeFilter<"Report"> | Date | string scan?: Prisma.XOR + ticketsForReport?: Prisma.TicketListRelationFilter + ticketsAsReanalysis?: Prisma.TicketListRelationFilter }, "id" | "scanId" | "code" | "share_token"> export type ReportOrderByWithAggregationInput = { @@ -335,6 +341,8 @@ export type ReportCreateInput = { createdAt?: Date | string updatedAt?: Date | string scan: Prisma.ScanCreateNestedOneWithoutReportInput + ticketsForReport?: Prisma.TicketCreateNestedManyWithoutReportInput + ticketsAsReanalysis?: Prisma.TicketCreateNestedManyWithoutReanalysisReportInput } export type ReportUncheckedCreateInput = { @@ -348,6 +356,8 @@ export type ReportUncheckedCreateInput = { processing: number createdAt?: Date | string updatedAt?: Date | string + ticketsForReport?: Prisma.TicketUncheckedCreateNestedManyWithoutReportInput + ticketsAsReanalysis?: Prisma.TicketUncheckedCreateNestedManyWithoutReanalysisReportInput } export type ReportUpdateInput = { @@ -361,6 +371,8 @@ export type ReportUpdateInput = { createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string scan?: Prisma.ScanUpdateOneRequiredWithoutReportNestedInput + ticketsForReport?: Prisma.TicketUpdateManyWithoutReportNestedInput + ticketsAsReanalysis?: Prisma.TicketUpdateManyWithoutReanalysisReportNestedInput } export type ReportUncheckedUpdateInput = { @@ -374,6 +386,8 @@ export type ReportUncheckedUpdateInput = { processing?: Prisma.FloatFieldUpdateOperationsInput | number createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + ticketsForReport?: Prisma.TicketUncheckedUpdateManyWithoutReportNestedInput + ticketsAsReanalysis?: Prisma.TicketUncheckedUpdateManyWithoutReanalysisReportNestedInput } export type ReportCreateManyInput = { @@ -498,6 +512,38 @@ export type ReportUncheckedUpdateOneWithoutScanNestedInput = { update?: Prisma.XOR, Prisma.ReportUncheckedUpdateWithoutScanInput> } +export type ReportCreateNestedOneWithoutTicketsForReportInput = { + create?: Prisma.XOR + connectOrCreate?: Prisma.ReportCreateOrConnectWithoutTicketsForReportInput + connect?: Prisma.ReportWhereUniqueInput +} + +export type ReportCreateNestedOneWithoutTicketsAsReanalysisInput = { + create?: Prisma.XOR + connectOrCreate?: Prisma.ReportCreateOrConnectWithoutTicketsAsReanalysisInput + connect?: Prisma.ReportWhereUniqueInput +} + +export type ReportUpdateOneWithoutTicketsForReportNestedInput = { + create?: Prisma.XOR + connectOrCreate?: Prisma.ReportCreateOrConnectWithoutTicketsForReportInput + upsert?: Prisma.ReportUpsertWithoutTicketsForReportInput + disconnect?: Prisma.ReportWhereInput | boolean + delete?: Prisma.ReportWhereInput | boolean + connect?: Prisma.ReportWhereUniqueInput + update?: Prisma.XOR, Prisma.ReportUncheckedUpdateWithoutTicketsForReportInput> +} + +export type ReportUpdateOneWithoutTicketsAsReanalysisNestedInput = { + create?: Prisma.XOR + connectOrCreate?: Prisma.ReportCreateOrConnectWithoutTicketsAsReanalysisInput + upsert?: Prisma.ReportUpsertWithoutTicketsAsReanalysisInput + disconnect?: Prisma.ReportWhereInput | boolean + delete?: Prisma.ReportWhereInput | boolean + connect?: Prisma.ReportWhereUniqueInput + update?: Prisma.XOR, Prisma.ReportUncheckedUpdateWithoutTicketsAsReanalysisInput> +} + export type ReportCreateWithoutScanInput = { id?: string content: Prisma.JsonNullValueInput | runtime.InputJsonValue @@ -508,6 +554,8 @@ export type ReportCreateWithoutScanInput = { processing: number createdAt?: Date | string updatedAt?: Date | string + ticketsForReport?: Prisma.TicketCreateNestedManyWithoutReportInput + ticketsAsReanalysis?: Prisma.TicketCreateNestedManyWithoutReanalysisReportInput } export type ReportUncheckedCreateWithoutScanInput = { @@ -520,6 +568,8 @@ export type ReportUncheckedCreateWithoutScanInput = { processing: number createdAt?: Date | string updatedAt?: Date | string + ticketsForReport?: Prisma.TicketUncheckedCreateNestedManyWithoutReportInput + ticketsAsReanalysis?: Prisma.TicketUncheckedCreateNestedManyWithoutReanalysisReportInput } export type ReportCreateOrConnectWithoutScanInput = { @@ -548,6 +598,8 @@ export type ReportUpdateWithoutScanInput = { processing?: Prisma.FloatFieldUpdateOperationsInput | number createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + ticketsForReport?: Prisma.TicketUpdateManyWithoutReportNestedInput + ticketsAsReanalysis?: Prisma.TicketUpdateManyWithoutReanalysisReportNestedInput } export type ReportUncheckedUpdateWithoutScanInput = { @@ -560,8 +612,192 @@ export type ReportUncheckedUpdateWithoutScanInput = { processing?: Prisma.FloatFieldUpdateOperationsInput | number createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + ticketsForReport?: Prisma.TicketUncheckedUpdateManyWithoutReportNestedInput + ticketsAsReanalysis?: Prisma.TicketUncheckedUpdateManyWithoutReanalysisReportNestedInput } +export type ReportCreateWithoutTicketsForReportInput = { + id?: string + content: Prisma.JsonNullValueInput | runtime.InputJsonValue + code: string + is_shared?: boolean + downloads?: number + share_token?: string | null + processing: number + createdAt?: Date | string + updatedAt?: Date | string + scan: Prisma.ScanCreateNestedOneWithoutReportInput + ticketsAsReanalysis?: Prisma.TicketCreateNestedManyWithoutReanalysisReportInput +} + +export type ReportUncheckedCreateWithoutTicketsForReportInput = { + id?: string + content: Prisma.JsonNullValueInput | runtime.InputJsonValue + scanId: string + code: string + is_shared?: boolean + downloads?: number + share_token?: string | null + processing: number + createdAt?: Date | string + updatedAt?: Date | string + ticketsAsReanalysis?: Prisma.TicketUncheckedCreateNestedManyWithoutReanalysisReportInput +} + +export type ReportCreateOrConnectWithoutTicketsForReportInput = { + where: Prisma.ReportWhereUniqueInput + create: Prisma.XOR +} + +export type ReportCreateWithoutTicketsAsReanalysisInput = { + id?: string + content: Prisma.JsonNullValueInput | runtime.InputJsonValue + code: string + is_shared?: boolean + downloads?: number + share_token?: string | null + processing: number + createdAt?: Date | string + updatedAt?: Date | string + scan: Prisma.ScanCreateNestedOneWithoutReportInput + ticketsForReport?: Prisma.TicketCreateNestedManyWithoutReportInput +} + +export type ReportUncheckedCreateWithoutTicketsAsReanalysisInput = { + id?: string + content: Prisma.JsonNullValueInput | runtime.InputJsonValue + scanId: string + code: string + is_shared?: boolean + downloads?: number + share_token?: string | null + processing: number + createdAt?: Date | string + updatedAt?: Date | string + ticketsForReport?: Prisma.TicketUncheckedCreateNestedManyWithoutReportInput +} + +export type ReportCreateOrConnectWithoutTicketsAsReanalysisInput = { + where: Prisma.ReportWhereUniqueInput + create: Prisma.XOR +} + +export type ReportUpsertWithoutTicketsForReportInput = { + update: Prisma.XOR + create: Prisma.XOR + where?: Prisma.ReportWhereInput +} + +export type ReportUpdateToOneWithWhereWithoutTicketsForReportInput = { + where?: Prisma.ReportWhereInput + data: Prisma.XOR +} + +export type ReportUpdateWithoutTicketsForReportInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + content?: Prisma.JsonNullValueInput | runtime.InputJsonValue + code?: Prisma.StringFieldUpdateOperationsInput | string + is_shared?: Prisma.BoolFieldUpdateOperationsInput | boolean + downloads?: Prisma.IntFieldUpdateOperationsInput | number + share_token?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + processing?: Prisma.FloatFieldUpdateOperationsInput | number + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + scan?: Prisma.ScanUpdateOneRequiredWithoutReportNestedInput + ticketsAsReanalysis?: Prisma.TicketUpdateManyWithoutReanalysisReportNestedInput +} + +export type ReportUncheckedUpdateWithoutTicketsForReportInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + content?: Prisma.JsonNullValueInput | runtime.InputJsonValue + scanId?: Prisma.StringFieldUpdateOperationsInput | string + code?: Prisma.StringFieldUpdateOperationsInput | string + is_shared?: Prisma.BoolFieldUpdateOperationsInput | boolean + downloads?: Prisma.IntFieldUpdateOperationsInput | number + share_token?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + processing?: Prisma.FloatFieldUpdateOperationsInput | number + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + ticketsAsReanalysis?: Prisma.TicketUncheckedUpdateManyWithoutReanalysisReportNestedInput +} + +export type ReportUpsertWithoutTicketsAsReanalysisInput = { + update: Prisma.XOR + create: Prisma.XOR + where?: Prisma.ReportWhereInput +} + +export type ReportUpdateToOneWithWhereWithoutTicketsAsReanalysisInput = { + where?: Prisma.ReportWhereInput + data: Prisma.XOR +} + +export type ReportUpdateWithoutTicketsAsReanalysisInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + content?: Prisma.JsonNullValueInput | runtime.InputJsonValue + code?: Prisma.StringFieldUpdateOperationsInput | string + is_shared?: Prisma.BoolFieldUpdateOperationsInput | boolean + downloads?: Prisma.IntFieldUpdateOperationsInput | number + share_token?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + processing?: Prisma.FloatFieldUpdateOperationsInput | number + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + scan?: Prisma.ScanUpdateOneRequiredWithoutReportNestedInput + ticketsForReport?: Prisma.TicketUpdateManyWithoutReportNestedInput +} + +export type ReportUncheckedUpdateWithoutTicketsAsReanalysisInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + content?: Prisma.JsonNullValueInput | runtime.InputJsonValue + scanId?: Prisma.StringFieldUpdateOperationsInput | string + code?: Prisma.StringFieldUpdateOperationsInput | string + is_shared?: Prisma.BoolFieldUpdateOperationsInput | boolean + downloads?: Prisma.IntFieldUpdateOperationsInput | number + share_token?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + processing?: Prisma.FloatFieldUpdateOperationsInput | number + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + ticketsForReport?: Prisma.TicketUncheckedUpdateManyWithoutReportNestedInput +} + + +/** + * Count Type ReportCountOutputType + */ + +export type ReportCountOutputType = { + ticketsForReport: number + ticketsAsReanalysis: number +} + +export type ReportCountOutputTypeSelect = { + ticketsForReport?: boolean | ReportCountOutputTypeCountTicketsForReportArgs + ticketsAsReanalysis?: boolean | ReportCountOutputTypeCountTicketsAsReanalysisArgs +} + +/** + * ReportCountOutputType without action + */ +export type ReportCountOutputTypeDefaultArgs = { + /** + * Select specific fields to fetch from the ReportCountOutputType + */ + select?: Prisma.ReportCountOutputTypeSelect | null +} + +/** + * ReportCountOutputType without action + */ +export type ReportCountOutputTypeCountTicketsForReportArgs = { + where?: Prisma.TicketWhereInput +} + +/** + * ReportCountOutputType without action + */ +export type ReportCountOutputTypeCountTicketsAsReanalysisArgs = { + where?: Prisma.TicketWhereInput +} export type ReportSelect = runtime.Types.Extensions.GetSelect<{ @@ -576,6 +812,9 @@ export type ReportSelect + ticketsForReport?: boolean | Prisma.Report$ticketsForReportArgs + ticketsAsReanalysis?: boolean | Prisma.Report$ticketsAsReanalysisArgs + _count?: boolean | Prisma.ReportCountOutputTypeDefaultArgs }, ExtArgs["result"]["report"]> export type ReportSelectCreateManyAndReturn = runtime.Types.Extensions.GetSelect<{ @@ -622,6 +861,9 @@ export type ReportSelectScalar = { export type ReportOmit = runtime.Types.Extensions.GetOmit<"id" | "content" | "scanId" | "code" | "is_shared" | "downloads" | "share_token" | "processing" | "createdAt" | "updatedAt", ExtArgs["result"]["report"]> export type ReportInclude = { scan?: boolean | Prisma.ScanDefaultArgs + ticketsForReport?: boolean | Prisma.Report$ticketsForReportArgs + ticketsAsReanalysis?: boolean | Prisma.Report$ticketsAsReanalysisArgs + _count?: boolean | Prisma.ReportCountOutputTypeDefaultArgs } export type ReportIncludeCreateManyAndReturn = { scan?: boolean | Prisma.ScanDefaultArgs @@ -634,6 +876,8 @@ export type $ReportPayload + ticketsForReport: Prisma.$TicketPayload[] + ticketsAsReanalysis: Prisma.$TicketPayload[] } scalars: runtime.Types.Extensions.GetPayloadResult<{ id: string @@ -1041,6 +1285,8 @@ readonly fields: ReportFieldRefs; export interface Prisma__ReportClient extends Prisma.PrismaPromise { readonly [Symbol.toStringTag]: "PrismaPromise" scan = {}>(args?: Prisma.Subset>): Prisma.Prisma__ScanClient, T, "findUniqueOrThrow", GlobalOmitOptions> | Null, Null, ExtArgs, GlobalOmitOptions> + ticketsForReport = {}>(args?: Prisma.Subset>): Prisma.PrismaPromise, T, "findMany", GlobalOmitOptions> | Null> + ticketsAsReanalysis = {}>(args?: Prisma.Subset>): Prisma.PrismaPromise, T, "findMany", GlobalOmitOptions> | Null> /** * Attaches callbacks for the resolution and/or rejection of the Promise. * @param onfulfilled The callback to execute when the Promise is resolved. @@ -1480,6 +1726,54 @@ export type ReportDeleteManyArgs = { + /** + * Select specific fields to fetch from the Ticket + */ + select?: Prisma.TicketSelect | null + /** + * Omit specific fields from the Ticket + */ + omit?: Prisma.TicketOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.TicketInclude | null + where?: Prisma.TicketWhereInput + orderBy?: Prisma.TicketOrderByWithRelationInput | Prisma.TicketOrderByWithRelationInput[] + cursor?: Prisma.TicketWhereUniqueInput + take?: number + skip?: number + distinct?: Prisma.TicketScalarFieldEnum | Prisma.TicketScalarFieldEnum[] +} + +/** + * Report.ticketsAsReanalysis + */ +export type Report$ticketsAsReanalysisArgs = { + /** + * Select specific fields to fetch from the Ticket + */ + select?: Prisma.TicketSelect | null + /** + * Omit specific fields from the Ticket + */ + omit?: Prisma.TicketOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.TicketInclude | null + where?: Prisma.TicketWhereInput + orderBy?: Prisma.TicketOrderByWithRelationInput | Prisma.TicketOrderByWithRelationInput[] + cursor?: Prisma.TicketWhereUniqueInput + take?: number + skip?: number + distinct?: Prisma.TicketScalarFieldEnum | Prisma.TicketScalarFieldEnum[] +} + /** * Report without action */ diff --git a/server/prisma/generated/client/models/Scan.ts b/server/prisma/generated/client/models/Scan.ts index 7ee3f71..eb96a43 100644 --- a/server/prisma/generated/client/models/Scan.ts +++ b/server/prisma/generated/client/models/Scan.ts @@ -293,6 +293,8 @@ export type ScanWhereInput = { organization?: Prisma.XOR | null scanImage?: Prisma.XOR | null report?: Prisma.XOR | null + ticketsForScan?: Prisma.TicketListRelationFilter + ticketsAsReanalysis?: Prisma.TicketListRelationFilter } export type ScanOrderByWithRelationInput = { @@ -315,6 +317,8 @@ export type ScanOrderByWithRelationInput = { organization?: Prisma.OrganizationOrderByWithRelationInput scanImage?: Prisma.ScanImageOrderByWithRelationInput report?: Prisma.ReportOrderByWithRelationInput + ticketsForScan?: Prisma.TicketOrderByRelationAggregateInput + ticketsAsReanalysis?: Prisma.TicketOrderByRelationAggregateInput } export type ScanWhereUniqueInput = Prisma.AtLeast<{ @@ -340,6 +344,8 @@ export type ScanWhereUniqueInput = Prisma.AtLeast<{ organization?: Prisma.XOR | null scanImage?: Prisma.XOR | null report?: Prisma.XOR | null + ticketsForScan?: Prisma.TicketListRelationFilter + ticketsAsReanalysis?: Prisma.TicketListRelationFilter }, "id" | "scan_code"> export type ScanOrderByWithAggregationInput = { @@ -401,6 +407,8 @@ export type ScanCreateInput = { organization?: Prisma.OrganizationCreateNestedOneWithoutScansInput scanImage?: Prisma.ScanImageCreateNestedOneWithoutScanInput report?: Prisma.ReportCreateNestedOneWithoutScanInput + ticketsForScan?: Prisma.TicketCreateNestedManyWithoutScanInput + ticketsAsReanalysis?: Prisma.TicketCreateNestedManyWithoutReanalysisScanInput } export type ScanUncheckedCreateInput = { @@ -420,6 +428,8 @@ export type ScanUncheckedCreateInput = { updatedAt?: Date | string scanImage?: Prisma.ScanImageUncheckedCreateNestedOneWithoutScanInput report?: Prisma.ReportUncheckedCreateNestedOneWithoutScanInput + ticketsForScan?: Prisma.TicketUncheckedCreateNestedManyWithoutScanInput + ticketsAsReanalysis?: Prisma.TicketUncheckedCreateNestedManyWithoutReanalysisScanInput } export type ScanUpdateInput = { @@ -439,6 +449,8 @@ export type ScanUpdateInput = { organization?: Prisma.OrganizationUpdateOneWithoutScansNestedInput scanImage?: Prisma.ScanImageUpdateOneWithoutScanNestedInput report?: Prisma.ReportUpdateOneWithoutScanNestedInput + ticketsForScan?: Prisma.TicketUpdateManyWithoutScanNestedInput + ticketsAsReanalysis?: Prisma.TicketUpdateManyWithoutReanalysisScanNestedInput } export type ScanUncheckedUpdateInput = { @@ -458,6 +470,8 @@ export type ScanUncheckedUpdateInput = { updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string scanImage?: Prisma.ScanImageUncheckedUpdateOneWithoutScanNestedInput report?: Prisma.ReportUncheckedUpdateOneWithoutScanNestedInput + ticketsForScan?: Prisma.TicketUncheckedUpdateManyWithoutScanNestedInput + ticketsAsReanalysis?: Prisma.TicketUncheckedUpdateManyWithoutReanalysisScanNestedInput } export type ScanCreateManyInput = { @@ -582,6 +596,11 @@ export type ScanScalarRelationFilter = { isNot?: Prisma.ScanWhereInput } +export type ScanNullableScalarRelationFilter = { + is?: Prisma.ScanWhereInput | null + isNot?: Prisma.ScanWhereInput | null +} + export type ScanCreateNestedManyWithoutUploaded_byInput = { create?: Prisma.XOR | Prisma.ScanCreateWithoutUploaded_byInput[] | Prisma.ScanUncheckedCreateWithoutUploaded_byInput[] connectOrCreate?: Prisma.ScanCreateOrConnectWithoutUploaded_byInput | Prisma.ScanCreateOrConnectWithoutUploaded_byInput[] @@ -752,6 +771,38 @@ export type ScanUpdateOneRequiredWithoutReportNestedInput = { update?: Prisma.XOR, Prisma.ScanUncheckedUpdateWithoutReportInput> } +export type ScanCreateNestedOneWithoutTicketsForScanInput = { + create?: Prisma.XOR + connectOrCreate?: Prisma.ScanCreateOrConnectWithoutTicketsForScanInput + connect?: Prisma.ScanWhereUniqueInput +} + +export type ScanCreateNestedOneWithoutTicketsAsReanalysisInput = { + create?: Prisma.XOR + connectOrCreate?: Prisma.ScanCreateOrConnectWithoutTicketsAsReanalysisInput + connect?: Prisma.ScanWhereUniqueInput +} + +export type ScanUpdateOneWithoutTicketsForScanNestedInput = { + create?: Prisma.XOR + connectOrCreate?: Prisma.ScanCreateOrConnectWithoutTicketsForScanInput + upsert?: Prisma.ScanUpsertWithoutTicketsForScanInput + disconnect?: Prisma.ScanWhereInput | boolean + delete?: Prisma.ScanWhereInput | boolean + connect?: Prisma.ScanWhereUniqueInput + update?: Prisma.XOR, Prisma.ScanUncheckedUpdateWithoutTicketsForScanInput> +} + +export type ScanUpdateOneWithoutTicketsAsReanalysisNestedInput = { + create?: Prisma.XOR + connectOrCreate?: Prisma.ScanCreateOrConnectWithoutTicketsAsReanalysisInput + upsert?: Prisma.ScanUpsertWithoutTicketsAsReanalysisInput + disconnect?: Prisma.ScanWhereInput | boolean + delete?: Prisma.ScanWhereInput | boolean + connect?: Prisma.ScanWhereUniqueInput + update?: Prisma.XOR, Prisma.ScanUncheckedUpdateWithoutTicketsAsReanalysisInput> +} + export type ScanCreateWithoutUploaded_byInput = { id?: string scan_code: string @@ -768,6 +819,8 @@ export type ScanCreateWithoutUploaded_byInput = { organization?: Prisma.OrganizationCreateNestedOneWithoutScansInput scanImage?: Prisma.ScanImageCreateNestedOneWithoutScanInput report?: Prisma.ReportCreateNestedOneWithoutScanInput + ticketsForScan?: Prisma.TicketCreateNestedManyWithoutScanInput + ticketsAsReanalysis?: Prisma.TicketCreateNestedManyWithoutReanalysisScanInput } export type ScanUncheckedCreateWithoutUploaded_byInput = { @@ -786,6 +839,8 @@ export type ScanUncheckedCreateWithoutUploaded_byInput = { updatedAt?: Date | string scanImage?: Prisma.ScanImageUncheckedCreateNestedOneWithoutScanInput report?: Prisma.ReportUncheckedCreateNestedOneWithoutScanInput + ticketsForScan?: Prisma.TicketUncheckedCreateNestedManyWithoutScanInput + ticketsAsReanalysis?: Prisma.TicketUncheckedCreateNestedManyWithoutReanalysisScanInput } export type ScanCreateOrConnectWithoutUploaded_byInput = { @@ -850,6 +905,8 @@ export type ScanCreateWithoutOrganizationInput = { patient?: Prisma.PatientCreateNestedOneWithoutScansInput scanImage?: Prisma.ScanImageCreateNestedOneWithoutScanInput report?: Prisma.ReportCreateNestedOneWithoutScanInput + ticketsForScan?: Prisma.TicketCreateNestedManyWithoutScanInput + ticketsAsReanalysis?: Prisma.TicketCreateNestedManyWithoutReanalysisScanInput } export type ScanUncheckedCreateWithoutOrganizationInput = { @@ -868,6 +925,8 @@ export type ScanUncheckedCreateWithoutOrganizationInput = { updatedAt?: Date | string scanImage?: Prisma.ScanImageUncheckedCreateNestedOneWithoutScanInput report?: Prisma.ReportUncheckedCreateNestedOneWithoutScanInput + ticketsForScan?: Prisma.TicketUncheckedCreateNestedManyWithoutScanInput + ticketsAsReanalysis?: Prisma.TicketUncheckedCreateNestedManyWithoutReanalysisScanInput } export type ScanCreateOrConnectWithoutOrganizationInput = { @@ -912,6 +971,8 @@ export type ScanCreateWithoutPatientInput = { organization?: Prisma.OrganizationCreateNestedOneWithoutScansInput scanImage?: Prisma.ScanImageCreateNestedOneWithoutScanInput report?: Prisma.ReportCreateNestedOneWithoutScanInput + ticketsForScan?: Prisma.TicketCreateNestedManyWithoutScanInput + ticketsAsReanalysis?: Prisma.TicketCreateNestedManyWithoutReanalysisScanInput } export type ScanUncheckedCreateWithoutPatientInput = { @@ -930,6 +991,8 @@ export type ScanUncheckedCreateWithoutPatientInput = { updatedAt?: Date | string scanImage?: Prisma.ScanImageUncheckedCreateNestedOneWithoutScanInput report?: Prisma.ReportUncheckedCreateNestedOneWithoutScanInput + ticketsForScan?: Prisma.TicketUncheckedCreateNestedManyWithoutScanInput + ticketsAsReanalysis?: Prisma.TicketUncheckedCreateNestedManyWithoutReanalysisScanInput } export type ScanCreateOrConnectWithoutPatientInput = { @@ -974,6 +1037,8 @@ export type ScanCreateWithoutScanImageInput = { patient?: Prisma.PatientCreateNestedOneWithoutScansInput organization?: Prisma.OrganizationCreateNestedOneWithoutScansInput report?: Prisma.ReportCreateNestedOneWithoutScanInput + ticketsForScan?: Prisma.TicketCreateNestedManyWithoutScanInput + ticketsAsReanalysis?: Prisma.TicketCreateNestedManyWithoutReanalysisScanInput } export type ScanUncheckedCreateWithoutScanImageInput = { @@ -992,6 +1057,8 @@ export type ScanUncheckedCreateWithoutScanImageInput = { createdAt?: Date | string updatedAt?: Date | string report?: Prisma.ReportUncheckedCreateNestedOneWithoutScanInput + ticketsForScan?: Prisma.TicketUncheckedCreateNestedManyWithoutScanInput + ticketsAsReanalysis?: Prisma.TicketUncheckedCreateNestedManyWithoutReanalysisScanInput } export type ScanCreateOrConnectWithoutScanImageInput = { @@ -1026,6 +1093,8 @@ export type ScanUpdateWithoutScanImageInput = { patient?: Prisma.PatientUpdateOneWithoutScansNestedInput organization?: Prisma.OrganizationUpdateOneWithoutScansNestedInput report?: Prisma.ReportUpdateOneWithoutScanNestedInput + ticketsForScan?: Prisma.TicketUpdateManyWithoutScanNestedInput + ticketsAsReanalysis?: Prisma.TicketUpdateManyWithoutReanalysisScanNestedInput } export type ScanUncheckedUpdateWithoutScanImageInput = { @@ -1044,6 +1113,8 @@ export type ScanUncheckedUpdateWithoutScanImageInput = { createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string report?: Prisma.ReportUncheckedUpdateOneWithoutScanNestedInput + ticketsForScan?: Prisma.TicketUncheckedUpdateManyWithoutScanNestedInput + ticketsAsReanalysis?: Prisma.TicketUncheckedUpdateManyWithoutReanalysisScanNestedInput } export type ScanCreateWithoutReportInput = { @@ -1062,6 +1133,8 @@ export type ScanCreateWithoutReportInput = { patient?: Prisma.PatientCreateNestedOneWithoutScansInput organization?: Prisma.OrganizationCreateNestedOneWithoutScansInput scanImage?: Prisma.ScanImageCreateNestedOneWithoutScanInput + ticketsForScan?: Prisma.TicketCreateNestedManyWithoutScanInput + ticketsAsReanalysis?: Prisma.TicketCreateNestedManyWithoutReanalysisScanInput } export type ScanUncheckedCreateWithoutReportInput = { @@ -1080,6 +1153,8 @@ export type ScanUncheckedCreateWithoutReportInput = { createdAt?: Date | string updatedAt?: Date | string scanImage?: Prisma.ScanImageUncheckedCreateNestedOneWithoutScanInput + ticketsForScan?: Prisma.TicketUncheckedCreateNestedManyWithoutScanInput + ticketsAsReanalysis?: Prisma.TicketUncheckedCreateNestedManyWithoutReanalysisScanInput } export type ScanCreateOrConnectWithoutReportInput = { @@ -1114,6 +1189,8 @@ export type ScanUpdateWithoutReportInput = { patient?: Prisma.PatientUpdateOneWithoutScansNestedInput organization?: Prisma.OrganizationUpdateOneWithoutScansNestedInput scanImage?: Prisma.ScanImageUpdateOneWithoutScanNestedInput + ticketsForScan?: Prisma.TicketUpdateManyWithoutScanNestedInput + ticketsAsReanalysis?: Prisma.TicketUpdateManyWithoutReanalysisScanNestedInput } export type ScanUncheckedUpdateWithoutReportInput = { @@ -1132,6 +1209,200 @@ export type ScanUncheckedUpdateWithoutReportInput = { createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string scanImage?: Prisma.ScanImageUncheckedUpdateOneWithoutScanNestedInput + ticketsForScan?: Prisma.TicketUncheckedUpdateManyWithoutScanNestedInput + ticketsAsReanalysis?: Prisma.TicketUncheckedUpdateManyWithoutReanalysisScanNestedInput +} + +export type ScanCreateWithoutTicketsForScanInput = { + id?: string + scan_code: string + name?: string | null + notes?: string | null + class: $Enums.Class + confidence_score: number + all_scores: Prisma.JsonNullValueInput | runtime.InputJsonValue + status?: $Enums.Status + processing: number + createdAt?: Date | string + updatedAt?: Date | string + uploaded_by: Prisma.UserCreateNestedOneWithoutScansInput + patient?: Prisma.PatientCreateNestedOneWithoutScansInput + organization?: Prisma.OrganizationCreateNestedOneWithoutScansInput + scanImage?: Prisma.ScanImageCreateNestedOneWithoutScanInput + report?: Prisma.ReportCreateNestedOneWithoutScanInput + ticketsAsReanalysis?: Prisma.TicketCreateNestedManyWithoutReanalysisScanInput +} + +export type ScanUncheckedCreateWithoutTicketsForScanInput = { + id?: string + scan_code: string + name?: string | null + notes?: string | null + class: $Enums.Class + confidence_score: number + all_scores: Prisma.JsonNullValueInput | runtime.InputJsonValue + status?: $Enums.Status + processing: number + uploadedById: string + patientId?: string | null + orgId?: string | null + createdAt?: Date | string + updatedAt?: Date | string + scanImage?: Prisma.ScanImageUncheckedCreateNestedOneWithoutScanInput + report?: Prisma.ReportUncheckedCreateNestedOneWithoutScanInput + ticketsAsReanalysis?: Prisma.TicketUncheckedCreateNestedManyWithoutReanalysisScanInput +} + +export type ScanCreateOrConnectWithoutTicketsForScanInput = { + where: Prisma.ScanWhereUniqueInput + create: Prisma.XOR +} + +export type ScanCreateWithoutTicketsAsReanalysisInput = { + id?: string + scan_code: string + name?: string | null + notes?: string | null + class: $Enums.Class + confidence_score: number + all_scores: Prisma.JsonNullValueInput | runtime.InputJsonValue + status?: $Enums.Status + processing: number + createdAt?: Date | string + updatedAt?: Date | string + uploaded_by: Prisma.UserCreateNestedOneWithoutScansInput + patient?: Prisma.PatientCreateNestedOneWithoutScansInput + organization?: Prisma.OrganizationCreateNestedOneWithoutScansInput + scanImage?: Prisma.ScanImageCreateNestedOneWithoutScanInput + report?: Prisma.ReportCreateNestedOneWithoutScanInput + ticketsForScan?: Prisma.TicketCreateNestedManyWithoutScanInput +} + +export type ScanUncheckedCreateWithoutTicketsAsReanalysisInput = { + id?: string + scan_code: string + name?: string | null + notes?: string | null + class: $Enums.Class + confidence_score: number + all_scores: Prisma.JsonNullValueInput | runtime.InputJsonValue + status?: $Enums.Status + processing: number + uploadedById: string + patientId?: string | null + orgId?: string | null + createdAt?: Date | string + updatedAt?: Date | string + scanImage?: Prisma.ScanImageUncheckedCreateNestedOneWithoutScanInput + report?: Prisma.ReportUncheckedCreateNestedOneWithoutScanInput + ticketsForScan?: Prisma.TicketUncheckedCreateNestedManyWithoutScanInput +} + +export type ScanCreateOrConnectWithoutTicketsAsReanalysisInput = { + where: Prisma.ScanWhereUniqueInput + create: Prisma.XOR +} + +export type ScanUpsertWithoutTicketsForScanInput = { + update: Prisma.XOR + create: Prisma.XOR + where?: Prisma.ScanWhereInput +} + +export type ScanUpdateToOneWithWhereWithoutTicketsForScanInput = { + where?: Prisma.ScanWhereInput + data: Prisma.XOR +} + +export type ScanUpdateWithoutTicketsForScanInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + scan_code?: Prisma.StringFieldUpdateOperationsInput | string + name?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + notes?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + class?: Prisma.EnumClassFieldUpdateOperationsInput | $Enums.Class + confidence_score?: Prisma.FloatFieldUpdateOperationsInput | number + all_scores?: Prisma.JsonNullValueInput | runtime.InputJsonValue + status?: Prisma.EnumStatusFieldUpdateOperationsInput | $Enums.Status + processing?: Prisma.FloatFieldUpdateOperationsInput | number + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + uploaded_by?: Prisma.UserUpdateOneRequiredWithoutScansNestedInput + patient?: Prisma.PatientUpdateOneWithoutScansNestedInput + organization?: Prisma.OrganizationUpdateOneWithoutScansNestedInput + scanImage?: Prisma.ScanImageUpdateOneWithoutScanNestedInput + report?: Prisma.ReportUpdateOneWithoutScanNestedInput + ticketsAsReanalysis?: Prisma.TicketUpdateManyWithoutReanalysisScanNestedInput +} + +export type ScanUncheckedUpdateWithoutTicketsForScanInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + scan_code?: Prisma.StringFieldUpdateOperationsInput | string + name?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + notes?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + class?: Prisma.EnumClassFieldUpdateOperationsInput | $Enums.Class + confidence_score?: Prisma.FloatFieldUpdateOperationsInput | number + all_scores?: Prisma.JsonNullValueInput | runtime.InputJsonValue + status?: Prisma.EnumStatusFieldUpdateOperationsInput | $Enums.Status + processing?: Prisma.FloatFieldUpdateOperationsInput | number + uploadedById?: Prisma.StringFieldUpdateOperationsInput | string + patientId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + orgId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + scanImage?: Prisma.ScanImageUncheckedUpdateOneWithoutScanNestedInput + report?: Prisma.ReportUncheckedUpdateOneWithoutScanNestedInput + ticketsAsReanalysis?: Prisma.TicketUncheckedUpdateManyWithoutReanalysisScanNestedInput +} + +export type ScanUpsertWithoutTicketsAsReanalysisInput = { + update: Prisma.XOR + create: Prisma.XOR + where?: Prisma.ScanWhereInput +} + +export type ScanUpdateToOneWithWhereWithoutTicketsAsReanalysisInput = { + where?: Prisma.ScanWhereInput + data: Prisma.XOR +} + +export type ScanUpdateWithoutTicketsAsReanalysisInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + scan_code?: Prisma.StringFieldUpdateOperationsInput | string + name?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + notes?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + class?: Prisma.EnumClassFieldUpdateOperationsInput | $Enums.Class + confidence_score?: Prisma.FloatFieldUpdateOperationsInput | number + all_scores?: Prisma.JsonNullValueInput | runtime.InputJsonValue + status?: Prisma.EnumStatusFieldUpdateOperationsInput | $Enums.Status + processing?: Prisma.FloatFieldUpdateOperationsInput | number + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + uploaded_by?: Prisma.UserUpdateOneRequiredWithoutScansNestedInput + patient?: Prisma.PatientUpdateOneWithoutScansNestedInput + organization?: Prisma.OrganizationUpdateOneWithoutScansNestedInput + scanImage?: Prisma.ScanImageUpdateOneWithoutScanNestedInput + report?: Prisma.ReportUpdateOneWithoutScanNestedInput + ticketsForScan?: Prisma.TicketUpdateManyWithoutScanNestedInput +} + +export type ScanUncheckedUpdateWithoutTicketsAsReanalysisInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + scan_code?: Prisma.StringFieldUpdateOperationsInput | string + name?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + notes?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + class?: Prisma.EnumClassFieldUpdateOperationsInput | $Enums.Class + confidence_score?: Prisma.FloatFieldUpdateOperationsInput | number + all_scores?: Prisma.JsonNullValueInput | runtime.InputJsonValue + status?: Prisma.EnumStatusFieldUpdateOperationsInput | $Enums.Status + processing?: Prisma.FloatFieldUpdateOperationsInput | number + uploadedById?: Prisma.StringFieldUpdateOperationsInput | string + patientId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + orgId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + scanImage?: Prisma.ScanImageUncheckedUpdateOneWithoutScanNestedInput + report?: Prisma.ReportUncheckedUpdateOneWithoutScanNestedInput + ticketsForScan?: Prisma.TicketUncheckedUpdateManyWithoutScanNestedInput } export type ScanCreateManyUploaded_byInput = { @@ -1166,6 +1437,8 @@ export type ScanUpdateWithoutUploaded_byInput = { organization?: Prisma.OrganizationUpdateOneWithoutScansNestedInput scanImage?: Prisma.ScanImageUpdateOneWithoutScanNestedInput report?: Prisma.ReportUpdateOneWithoutScanNestedInput + ticketsForScan?: Prisma.TicketUpdateManyWithoutScanNestedInput + ticketsAsReanalysis?: Prisma.TicketUpdateManyWithoutReanalysisScanNestedInput } export type ScanUncheckedUpdateWithoutUploaded_byInput = { @@ -1184,6 +1457,8 @@ export type ScanUncheckedUpdateWithoutUploaded_byInput = { updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string scanImage?: Prisma.ScanImageUncheckedUpdateOneWithoutScanNestedInput report?: Prisma.ReportUncheckedUpdateOneWithoutScanNestedInput + ticketsForScan?: Prisma.TicketUncheckedUpdateManyWithoutScanNestedInput + ticketsAsReanalysis?: Prisma.TicketUncheckedUpdateManyWithoutReanalysisScanNestedInput } export type ScanUncheckedUpdateManyWithoutUploaded_byInput = { @@ -1234,6 +1509,8 @@ export type ScanUpdateWithoutOrganizationInput = { patient?: Prisma.PatientUpdateOneWithoutScansNestedInput scanImage?: Prisma.ScanImageUpdateOneWithoutScanNestedInput report?: Prisma.ReportUpdateOneWithoutScanNestedInput + ticketsForScan?: Prisma.TicketUpdateManyWithoutScanNestedInput + ticketsAsReanalysis?: Prisma.TicketUpdateManyWithoutReanalysisScanNestedInput } export type ScanUncheckedUpdateWithoutOrganizationInput = { @@ -1252,6 +1529,8 @@ export type ScanUncheckedUpdateWithoutOrganizationInput = { updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string scanImage?: Prisma.ScanImageUncheckedUpdateOneWithoutScanNestedInput report?: Prisma.ReportUncheckedUpdateOneWithoutScanNestedInput + ticketsForScan?: Prisma.TicketUncheckedUpdateManyWithoutScanNestedInput + ticketsAsReanalysis?: Prisma.TicketUncheckedUpdateManyWithoutReanalysisScanNestedInput } export type ScanUncheckedUpdateManyWithoutOrganizationInput = { @@ -1302,6 +1581,8 @@ export type ScanUpdateWithoutPatientInput = { organization?: Prisma.OrganizationUpdateOneWithoutScansNestedInput scanImage?: Prisma.ScanImageUpdateOneWithoutScanNestedInput report?: Prisma.ReportUpdateOneWithoutScanNestedInput + ticketsForScan?: Prisma.TicketUpdateManyWithoutScanNestedInput + ticketsAsReanalysis?: Prisma.TicketUpdateManyWithoutReanalysisScanNestedInput } export type ScanUncheckedUpdateWithoutPatientInput = { @@ -1320,6 +1601,8 @@ export type ScanUncheckedUpdateWithoutPatientInput = { updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string scanImage?: Prisma.ScanImageUncheckedUpdateOneWithoutScanNestedInput report?: Prisma.ReportUncheckedUpdateOneWithoutScanNestedInput + ticketsForScan?: Prisma.TicketUncheckedUpdateManyWithoutScanNestedInput + ticketsAsReanalysis?: Prisma.TicketUncheckedUpdateManyWithoutReanalysisScanNestedInput } export type ScanUncheckedUpdateManyWithoutPatientInput = { @@ -1339,6 +1622,44 @@ export type ScanUncheckedUpdateManyWithoutPatientInput = { } +/** + * Count Type ScanCountOutputType + */ + +export type ScanCountOutputType = { + ticketsForScan: number + ticketsAsReanalysis: number +} + +export type ScanCountOutputTypeSelect = { + ticketsForScan?: boolean | ScanCountOutputTypeCountTicketsForScanArgs + ticketsAsReanalysis?: boolean | ScanCountOutputTypeCountTicketsAsReanalysisArgs +} + +/** + * ScanCountOutputType without action + */ +export type ScanCountOutputTypeDefaultArgs = { + /** + * Select specific fields to fetch from the ScanCountOutputType + */ + select?: Prisma.ScanCountOutputTypeSelect | null +} + +/** + * ScanCountOutputType without action + */ +export type ScanCountOutputTypeCountTicketsForScanArgs = { + where?: Prisma.TicketWhereInput +} + +/** + * ScanCountOutputType without action + */ +export type ScanCountOutputTypeCountTicketsAsReanalysisArgs = { + where?: Prisma.TicketWhereInput +} + export type ScanSelect = runtime.Types.Extensions.GetSelect<{ id?: boolean @@ -1360,6 +1681,9 @@ export type ScanSelect scanImage?: boolean | Prisma.Scan$scanImageArgs report?: boolean | Prisma.Scan$reportArgs + ticketsForScan?: boolean | Prisma.Scan$ticketsForScanArgs + ticketsAsReanalysis?: boolean | Prisma.Scan$ticketsAsReanalysisArgs + _count?: boolean | Prisma.ScanCountOutputTypeDefaultArgs }, ExtArgs["result"]["scan"]> export type ScanSelectCreateManyAndReturn = runtime.Types.Extensions.GetSelect<{ @@ -1426,6 +1750,9 @@ export type ScanInclude scanImage?: boolean | Prisma.Scan$scanImageArgs report?: boolean | Prisma.Scan$reportArgs + ticketsForScan?: boolean | Prisma.Scan$ticketsForScanArgs + ticketsAsReanalysis?: boolean | Prisma.Scan$ticketsAsReanalysisArgs + _count?: boolean | Prisma.ScanCountOutputTypeDefaultArgs } export type ScanIncludeCreateManyAndReturn = { uploaded_by?: boolean | Prisma.UserDefaultArgs @@ -1446,6 +1773,8 @@ export type $ScanPayload | null scanImage: Prisma.$ScanImagePayload | null report: Prisma.$ReportPayload | null + ticketsForScan: Prisma.$TicketPayload[] + ticketsAsReanalysis: Prisma.$TicketPayload[] } scalars: runtime.Types.Extensions.GetPayloadResult<{ id: string @@ -1861,6 +2190,8 @@ export interface Prisma__ScanClient = {}>(args?: Prisma.Subset>): Prisma.Prisma__OrganizationClient, T, "findUniqueOrThrow", GlobalOmitOptions> | null, null, ExtArgs, GlobalOmitOptions> scanImage = {}>(args?: Prisma.Subset>): Prisma.Prisma__ScanImageClient, T, "findUniqueOrThrow", GlobalOmitOptions> | null, null, ExtArgs, GlobalOmitOptions> report = {}>(args?: Prisma.Subset>): Prisma.Prisma__ReportClient, T, "findUniqueOrThrow", GlobalOmitOptions> | null, null, ExtArgs, GlobalOmitOptions> + ticketsForScan = {}>(args?: Prisma.Subset>): Prisma.PrismaPromise, T, "findMany", GlobalOmitOptions> | Null> + ticketsAsReanalysis = {}>(args?: Prisma.Subset>): Prisma.PrismaPromise, T, "findMany", GlobalOmitOptions> | Null> /** * Attaches callbacks for the resolution and/or rejection of the Promise. * @param onfulfilled The callback to execute when the Promise is resolved. @@ -2380,6 +2711,54 @@ export type Scan$reportArgs = { + /** + * Select specific fields to fetch from the Ticket + */ + select?: Prisma.TicketSelect | null + /** + * Omit specific fields from the Ticket + */ + omit?: Prisma.TicketOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.TicketInclude | null + where?: Prisma.TicketWhereInput + orderBy?: Prisma.TicketOrderByWithRelationInput | Prisma.TicketOrderByWithRelationInput[] + cursor?: Prisma.TicketWhereUniqueInput + take?: number + skip?: number + distinct?: Prisma.TicketScalarFieldEnum | Prisma.TicketScalarFieldEnum[] +} + +/** + * Scan.ticketsAsReanalysis + */ +export type Scan$ticketsAsReanalysisArgs = { + /** + * Select specific fields to fetch from the Ticket + */ + select?: Prisma.TicketSelect | null + /** + * Omit specific fields from the Ticket + */ + omit?: Prisma.TicketOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.TicketInclude | null + where?: Prisma.TicketWhereInput + orderBy?: Prisma.TicketOrderByWithRelationInput | Prisma.TicketOrderByWithRelationInput[] + cursor?: Prisma.TicketWhereUniqueInput + take?: number + skip?: number + distinct?: Prisma.TicketScalarFieldEnum | Prisma.TicketScalarFieldEnum[] +} + /** * Scan without action */ diff --git a/server/prisma/generated/client/models/Ticket.ts b/server/prisma/generated/client/models/Ticket.ts new file mode 100644 index 0000000..0c27886 --- /dev/null +++ b/server/prisma/generated/client/models/Ticket.ts @@ -0,0 +1,2767 @@ + +/* !!! This is code generated by Prisma. Do not edit directly. !!! */ +/* eslint-disable */ +// biome-ignore-all lint: generated file +// @ts-nocheck +/* + * This file exports the `Ticket` model and its related types. + * + * 🟢 You can import this file directly. + */ +import type * as runtime from "@prisma/client/runtime/client" +import type * as $Enums from "../enums.js" +import type * as Prisma from "../internal/prismaNamespace.js" + +/** + * Model Ticket + * + */ +export type TicketModel = runtime.Types.Result.DefaultSelection + +export type AggregateTicket = { + _count: TicketCountAggregateOutputType | null + _min: TicketMinAggregateOutputType | null + _max: TicketMaxAggregateOutputType | null +} + +export type TicketMinAggregateOutputType = { + id: string | null + code: string | null + type: $Enums.TicketType | null + status: $Enums.TicketStatus | null + priority: $Enums.TicketPriority | null + reason: string | null + scanId: string | null + reportId: string | null + submittedById: string | null + assignedToId: string | null + resolutionNote: string | null + reanalysisScanId: string | null + reanalysisReportId: string | null + createdAt: Date | null + updatedAt: Date | null + resolvedAt: Date | null +} + +export type TicketMaxAggregateOutputType = { + id: string | null + code: string | null + type: $Enums.TicketType | null + status: $Enums.TicketStatus | null + priority: $Enums.TicketPriority | null + reason: string | null + scanId: string | null + reportId: string | null + submittedById: string | null + assignedToId: string | null + resolutionNote: string | null + reanalysisScanId: string | null + reanalysisReportId: string | null + createdAt: Date | null + updatedAt: Date | null + resolvedAt: Date | null +} + +export type TicketCountAggregateOutputType = { + id: number + code: number + type: number + status: number + priority: number + reason: number + scanId: number + reportId: number + submittedById: number + assignedToId: number + resolutionNote: number + reanalysisScanId: number + reanalysisReportId: number + createdAt: number + updatedAt: number + resolvedAt: number + _all: number +} + + +export type TicketMinAggregateInputType = { + id?: true + code?: true + type?: true + status?: true + priority?: true + reason?: true + scanId?: true + reportId?: true + submittedById?: true + assignedToId?: true + resolutionNote?: true + reanalysisScanId?: true + reanalysisReportId?: true + createdAt?: true + updatedAt?: true + resolvedAt?: true +} + +export type TicketMaxAggregateInputType = { + id?: true + code?: true + type?: true + status?: true + priority?: true + reason?: true + scanId?: true + reportId?: true + submittedById?: true + assignedToId?: true + resolutionNote?: true + reanalysisScanId?: true + reanalysisReportId?: true + createdAt?: true + updatedAt?: true + resolvedAt?: true +} + +export type TicketCountAggregateInputType = { + id?: true + code?: true + type?: true + status?: true + priority?: true + reason?: true + scanId?: true + reportId?: true + submittedById?: true + assignedToId?: true + resolutionNote?: true + reanalysisScanId?: true + reanalysisReportId?: true + createdAt?: true + updatedAt?: true + resolvedAt?: true + _all?: true +} + +export type TicketAggregateArgs = { + /** + * Filter which Ticket to aggregate. + */ + where?: Prisma.TicketWhereInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/sorting Sorting Docs} + * + * Determine the order of Tickets to fetch. + */ + orderBy?: Prisma.TicketOrderByWithRelationInput | Prisma.TicketOrderByWithRelationInput[] + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination#cursor-based-pagination Cursor Docs} + * + * Sets the start position + */ + cursor?: Prisma.TicketWhereUniqueInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Take `±n` Tickets from the position of the cursor. + */ + take?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Skip the first `n` Tickets. + */ + skip?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Count returned Tickets + **/ + _count?: true | TicketCountAggregateInputType + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Select which fields to find the minimum value + **/ + _min?: TicketMinAggregateInputType + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Select which fields to find the maximum value + **/ + _max?: TicketMaxAggregateInputType +} + +export type GetTicketAggregateType = { + [P in keyof T & keyof AggregateTicket]: P extends '_count' | 'count' + ? T[P] extends true + ? number + : Prisma.GetScalarType + : Prisma.GetScalarType +} + + + + +export type TicketGroupByArgs = { + where?: Prisma.TicketWhereInput + orderBy?: Prisma.TicketOrderByWithAggregationInput | Prisma.TicketOrderByWithAggregationInput[] + by: Prisma.TicketScalarFieldEnum[] | Prisma.TicketScalarFieldEnum + having?: Prisma.TicketScalarWhereWithAggregatesInput + take?: number + skip?: number + _count?: TicketCountAggregateInputType | true + _min?: TicketMinAggregateInputType + _max?: TicketMaxAggregateInputType +} + +export type TicketGroupByOutputType = { + id: string + code: string + type: $Enums.TicketType + status: $Enums.TicketStatus + priority: $Enums.TicketPriority + reason: string + scanId: string | null + reportId: string | null + submittedById: string + assignedToId: string | null + resolutionNote: string | null + reanalysisScanId: string | null + reanalysisReportId: string | null + createdAt: Date + updatedAt: Date + resolvedAt: Date | null + _count: TicketCountAggregateOutputType | null + _min: TicketMinAggregateOutputType | null + _max: TicketMaxAggregateOutputType | null +} + +export type GetTicketGroupByPayload = Prisma.PrismaPromise< + Array< + Prisma.PickEnumerable & + { + [P in ((keyof T) & (keyof TicketGroupByOutputType))]: P extends '_count' + ? T[P] extends boolean + ? number + : Prisma.GetScalarType + : Prisma.GetScalarType + } + > + > + + + +export type TicketWhereInput = { + AND?: Prisma.TicketWhereInput | Prisma.TicketWhereInput[] + OR?: Prisma.TicketWhereInput[] + NOT?: Prisma.TicketWhereInput | Prisma.TicketWhereInput[] + id?: Prisma.StringFilter<"Ticket"> | string + code?: Prisma.StringFilter<"Ticket"> | string + type?: Prisma.EnumTicketTypeFilter<"Ticket"> | $Enums.TicketType + status?: Prisma.EnumTicketStatusFilter<"Ticket"> | $Enums.TicketStatus + priority?: Prisma.EnumTicketPriorityFilter<"Ticket"> | $Enums.TicketPriority + reason?: Prisma.StringFilter<"Ticket"> | string + scanId?: Prisma.StringNullableFilter<"Ticket"> | string | null + reportId?: Prisma.StringNullableFilter<"Ticket"> | string | null + submittedById?: Prisma.StringFilter<"Ticket"> | string + assignedToId?: Prisma.StringNullableFilter<"Ticket"> | string | null + resolutionNote?: Prisma.StringNullableFilter<"Ticket"> | string | null + reanalysisScanId?: Prisma.StringNullableFilter<"Ticket"> | string | null + reanalysisReportId?: Prisma.StringNullableFilter<"Ticket"> | string | null + createdAt?: Prisma.DateTimeFilter<"Ticket"> | Date | string + updatedAt?: Prisma.DateTimeFilter<"Ticket"> | Date | string + resolvedAt?: Prisma.DateTimeNullableFilter<"Ticket"> | Date | string | null + scan?: Prisma.XOR | null + report?: Prisma.XOR | null + submittedBy?: Prisma.XOR + assignedTo?: Prisma.XOR | null + reanalysisScan?: Prisma.XOR | null + reanalysisReport?: Prisma.XOR | null +} + +export type TicketOrderByWithRelationInput = { + id?: Prisma.SortOrder + code?: Prisma.SortOrder + type?: Prisma.SortOrder + status?: Prisma.SortOrder + priority?: Prisma.SortOrder + reason?: Prisma.SortOrder + scanId?: Prisma.SortOrderInput | Prisma.SortOrder + reportId?: Prisma.SortOrderInput | Prisma.SortOrder + submittedById?: Prisma.SortOrder + assignedToId?: Prisma.SortOrderInput | Prisma.SortOrder + resolutionNote?: Prisma.SortOrderInput | Prisma.SortOrder + reanalysisScanId?: Prisma.SortOrderInput | Prisma.SortOrder + reanalysisReportId?: Prisma.SortOrderInput | Prisma.SortOrder + createdAt?: Prisma.SortOrder + updatedAt?: Prisma.SortOrder + resolvedAt?: Prisma.SortOrderInput | Prisma.SortOrder + scan?: Prisma.ScanOrderByWithRelationInput + report?: Prisma.ReportOrderByWithRelationInput + submittedBy?: Prisma.UserOrderByWithRelationInput + assignedTo?: Prisma.UserOrderByWithRelationInput + reanalysisScan?: Prisma.ScanOrderByWithRelationInput + reanalysisReport?: Prisma.ReportOrderByWithRelationInput +} + +export type TicketWhereUniqueInput = Prisma.AtLeast<{ + id?: string + code?: string + AND?: Prisma.TicketWhereInput | Prisma.TicketWhereInput[] + OR?: Prisma.TicketWhereInput[] + NOT?: Prisma.TicketWhereInput | Prisma.TicketWhereInput[] + type?: Prisma.EnumTicketTypeFilter<"Ticket"> | $Enums.TicketType + status?: Prisma.EnumTicketStatusFilter<"Ticket"> | $Enums.TicketStatus + priority?: Prisma.EnumTicketPriorityFilter<"Ticket"> | $Enums.TicketPriority + reason?: Prisma.StringFilter<"Ticket"> | string + scanId?: Prisma.StringNullableFilter<"Ticket"> | string | null + reportId?: Prisma.StringNullableFilter<"Ticket"> | string | null + submittedById?: Prisma.StringFilter<"Ticket"> | string + assignedToId?: Prisma.StringNullableFilter<"Ticket"> | string | null + resolutionNote?: Prisma.StringNullableFilter<"Ticket"> | string | null + reanalysisScanId?: Prisma.StringNullableFilter<"Ticket"> | string | null + reanalysisReportId?: Prisma.StringNullableFilter<"Ticket"> | string | null + createdAt?: Prisma.DateTimeFilter<"Ticket"> | Date | string + updatedAt?: Prisma.DateTimeFilter<"Ticket"> | Date | string + resolvedAt?: Prisma.DateTimeNullableFilter<"Ticket"> | Date | string | null + scan?: Prisma.XOR | null + report?: Prisma.XOR | null + submittedBy?: Prisma.XOR + assignedTo?: Prisma.XOR | null + reanalysisScan?: Prisma.XOR | null + reanalysisReport?: Prisma.XOR | null +}, "id" | "code"> + +export type TicketOrderByWithAggregationInput = { + id?: Prisma.SortOrder + code?: Prisma.SortOrder + type?: Prisma.SortOrder + status?: Prisma.SortOrder + priority?: Prisma.SortOrder + reason?: Prisma.SortOrder + scanId?: Prisma.SortOrderInput | Prisma.SortOrder + reportId?: Prisma.SortOrderInput | Prisma.SortOrder + submittedById?: Prisma.SortOrder + assignedToId?: Prisma.SortOrderInput | Prisma.SortOrder + resolutionNote?: Prisma.SortOrderInput | Prisma.SortOrder + reanalysisScanId?: Prisma.SortOrderInput | Prisma.SortOrder + reanalysisReportId?: Prisma.SortOrderInput | Prisma.SortOrder + createdAt?: Prisma.SortOrder + updatedAt?: Prisma.SortOrder + resolvedAt?: Prisma.SortOrderInput | Prisma.SortOrder + _count?: Prisma.TicketCountOrderByAggregateInput + _max?: Prisma.TicketMaxOrderByAggregateInput + _min?: Prisma.TicketMinOrderByAggregateInput +} + +export type TicketScalarWhereWithAggregatesInput = { + AND?: Prisma.TicketScalarWhereWithAggregatesInput | Prisma.TicketScalarWhereWithAggregatesInput[] + OR?: Prisma.TicketScalarWhereWithAggregatesInput[] + NOT?: Prisma.TicketScalarWhereWithAggregatesInput | Prisma.TicketScalarWhereWithAggregatesInput[] + id?: Prisma.StringWithAggregatesFilter<"Ticket"> | string + code?: Prisma.StringWithAggregatesFilter<"Ticket"> | string + type?: Prisma.EnumTicketTypeWithAggregatesFilter<"Ticket"> | $Enums.TicketType + status?: Prisma.EnumTicketStatusWithAggregatesFilter<"Ticket"> | $Enums.TicketStatus + priority?: Prisma.EnumTicketPriorityWithAggregatesFilter<"Ticket"> | $Enums.TicketPriority + reason?: Prisma.StringWithAggregatesFilter<"Ticket"> | string + scanId?: Prisma.StringNullableWithAggregatesFilter<"Ticket"> | string | null + reportId?: Prisma.StringNullableWithAggregatesFilter<"Ticket"> | string | null + submittedById?: Prisma.StringWithAggregatesFilter<"Ticket"> | string + assignedToId?: Prisma.StringNullableWithAggregatesFilter<"Ticket"> | string | null + resolutionNote?: Prisma.StringNullableWithAggregatesFilter<"Ticket"> | string | null + reanalysisScanId?: Prisma.StringNullableWithAggregatesFilter<"Ticket"> | string | null + reanalysisReportId?: Prisma.StringNullableWithAggregatesFilter<"Ticket"> | string | null + createdAt?: Prisma.DateTimeWithAggregatesFilter<"Ticket"> | Date | string + updatedAt?: Prisma.DateTimeWithAggregatesFilter<"Ticket"> | Date | string + resolvedAt?: Prisma.DateTimeNullableWithAggregatesFilter<"Ticket"> | Date | string | null +} + +export type TicketCreateInput = { + id?: string + code: string + type: $Enums.TicketType + status?: $Enums.TicketStatus + priority?: $Enums.TicketPriority + reason: string + resolutionNote?: string | null + createdAt?: Date | string + updatedAt?: Date | string + resolvedAt?: Date | string | null + scan?: Prisma.ScanCreateNestedOneWithoutTicketsForScanInput + report?: Prisma.ReportCreateNestedOneWithoutTicketsForReportInput + submittedBy: Prisma.UserCreateNestedOneWithoutSubmittedTicketsInput + assignedTo?: Prisma.UserCreateNestedOneWithoutAssignedTicketsInput + reanalysisScan?: Prisma.ScanCreateNestedOneWithoutTicketsAsReanalysisInput + reanalysisReport?: Prisma.ReportCreateNestedOneWithoutTicketsAsReanalysisInput +} + +export type TicketUncheckedCreateInput = { + id?: string + code: string + type: $Enums.TicketType + status?: $Enums.TicketStatus + priority?: $Enums.TicketPriority + reason: string + scanId?: string | null + reportId?: string | null + submittedById: string + assignedToId?: string | null + resolutionNote?: string | null + reanalysisScanId?: string | null + reanalysisReportId?: string | null + createdAt?: Date | string + updatedAt?: Date | string + resolvedAt?: Date | string | null +} + +export type TicketUpdateInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + code?: Prisma.StringFieldUpdateOperationsInput | string + type?: Prisma.EnumTicketTypeFieldUpdateOperationsInput | $Enums.TicketType + status?: Prisma.EnumTicketStatusFieldUpdateOperationsInput | $Enums.TicketStatus + priority?: Prisma.EnumTicketPriorityFieldUpdateOperationsInput | $Enums.TicketPriority + reason?: Prisma.StringFieldUpdateOperationsInput | string + resolutionNote?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + resolvedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null + scan?: Prisma.ScanUpdateOneWithoutTicketsForScanNestedInput + report?: Prisma.ReportUpdateOneWithoutTicketsForReportNestedInput + submittedBy?: Prisma.UserUpdateOneRequiredWithoutSubmittedTicketsNestedInput + assignedTo?: Prisma.UserUpdateOneWithoutAssignedTicketsNestedInput + reanalysisScan?: Prisma.ScanUpdateOneWithoutTicketsAsReanalysisNestedInput + reanalysisReport?: Prisma.ReportUpdateOneWithoutTicketsAsReanalysisNestedInput +} + +export type TicketUncheckedUpdateInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + code?: Prisma.StringFieldUpdateOperationsInput | string + type?: Prisma.EnumTicketTypeFieldUpdateOperationsInput | $Enums.TicketType + status?: Prisma.EnumTicketStatusFieldUpdateOperationsInput | $Enums.TicketStatus + priority?: Prisma.EnumTicketPriorityFieldUpdateOperationsInput | $Enums.TicketPriority + reason?: Prisma.StringFieldUpdateOperationsInput | string + scanId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + reportId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + submittedById?: Prisma.StringFieldUpdateOperationsInput | string + assignedToId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + resolutionNote?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + reanalysisScanId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + reanalysisReportId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + resolvedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null +} + +export type TicketCreateManyInput = { + id?: string + code: string + type: $Enums.TicketType + status?: $Enums.TicketStatus + priority?: $Enums.TicketPriority + reason: string + scanId?: string | null + reportId?: string | null + submittedById: string + assignedToId?: string | null + resolutionNote?: string | null + reanalysisScanId?: string | null + reanalysisReportId?: string | null + createdAt?: Date | string + updatedAt?: Date | string + resolvedAt?: Date | string | null +} + +export type TicketUpdateManyMutationInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + code?: Prisma.StringFieldUpdateOperationsInput | string + type?: Prisma.EnumTicketTypeFieldUpdateOperationsInput | $Enums.TicketType + status?: Prisma.EnumTicketStatusFieldUpdateOperationsInput | $Enums.TicketStatus + priority?: Prisma.EnumTicketPriorityFieldUpdateOperationsInput | $Enums.TicketPriority + reason?: Prisma.StringFieldUpdateOperationsInput | string + resolutionNote?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + resolvedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null +} + +export type TicketUncheckedUpdateManyInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + code?: Prisma.StringFieldUpdateOperationsInput | string + type?: Prisma.EnumTicketTypeFieldUpdateOperationsInput | $Enums.TicketType + status?: Prisma.EnumTicketStatusFieldUpdateOperationsInput | $Enums.TicketStatus + priority?: Prisma.EnumTicketPriorityFieldUpdateOperationsInput | $Enums.TicketPriority + reason?: Prisma.StringFieldUpdateOperationsInput | string + scanId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + reportId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + submittedById?: Prisma.StringFieldUpdateOperationsInput | string + assignedToId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + resolutionNote?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + reanalysisScanId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + reanalysisReportId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + resolvedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null +} + +export type TicketListRelationFilter = { + every?: Prisma.TicketWhereInput + some?: Prisma.TicketWhereInput + none?: Prisma.TicketWhereInput +} + +export type TicketOrderByRelationAggregateInput = { + _count?: Prisma.SortOrder +} + +export type TicketCountOrderByAggregateInput = { + id?: Prisma.SortOrder + code?: Prisma.SortOrder + type?: Prisma.SortOrder + status?: Prisma.SortOrder + priority?: Prisma.SortOrder + reason?: Prisma.SortOrder + scanId?: Prisma.SortOrder + reportId?: Prisma.SortOrder + submittedById?: Prisma.SortOrder + assignedToId?: Prisma.SortOrder + resolutionNote?: Prisma.SortOrder + reanalysisScanId?: Prisma.SortOrder + reanalysisReportId?: Prisma.SortOrder + createdAt?: Prisma.SortOrder + updatedAt?: Prisma.SortOrder + resolvedAt?: Prisma.SortOrder +} + +export type TicketMaxOrderByAggregateInput = { + id?: Prisma.SortOrder + code?: Prisma.SortOrder + type?: Prisma.SortOrder + status?: Prisma.SortOrder + priority?: Prisma.SortOrder + reason?: Prisma.SortOrder + scanId?: Prisma.SortOrder + reportId?: Prisma.SortOrder + submittedById?: Prisma.SortOrder + assignedToId?: Prisma.SortOrder + resolutionNote?: Prisma.SortOrder + reanalysisScanId?: Prisma.SortOrder + reanalysisReportId?: Prisma.SortOrder + createdAt?: Prisma.SortOrder + updatedAt?: Prisma.SortOrder + resolvedAt?: Prisma.SortOrder +} + +export type TicketMinOrderByAggregateInput = { + id?: Prisma.SortOrder + code?: Prisma.SortOrder + type?: Prisma.SortOrder + status?: Prisma.SortOrder + priority?: Prisma.SortOrder + reason?: Prisma.SortOrder + scanId?: Prisma.SortOrder + reportId?: Prisma.SortOrder + submittedById?: Prisma.SortOrder + assignedToId?: Prisma.SortOrder + resolutionNote?: Prisma.SortOrder + reanalysisScanId?: Prisma.SortOrder + reanalysisReportId?: Prisma.SortOrder + createdAt?: Prisma.SortOrder + updatedAt?: Prisma.SortOrder + resolvedAt?: Prisma.SortOrder +} + +export type TicketCreateNestedManyWithoutSubmittedByInput = { + create?: Prisma.XOR | Prisma.TicketCreateWithoutSubmittedByInput[] | Prisma.TicketUncheckedCreateWithoutSubmittedByInput[] + connectOrCreate?: Prisma.TicketCreateOrConnectWithoutSubmittedByInput | Prisma.TicketCreateOrConnectWithoutSubmittedByInput[] + createMany?: Prisma.TicketCreateManySubmittedByInputEnvelope + connect?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] +} + +export type TicketCreateNestedManyWithoutAssignedToInput = { + create?: Prisma.XOR | Prisma.TicketCreateWithoutAssignedToInput[] | Prisma.TicketUncheckedCreateWithoutAssignedToInput[] + connectOrCreate?: Prisma.TicketCreateOrConnectWithoutAssignedToInput | Prisma.TicketCreateOrConnectWithoutAssignedToInput[] + createMany?: Prisma.TicketCreateManyAssignedToInputEnvelope + connect?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] +} + +export type TicketUncheckedCreateNestedManyWithoutSubmittedByInput = { + create?: Prisma.XOR | Prisma.TicketCreateWithoutSubmittedByInput[] | Prisma.TicketUncheckedCreateWithoutSubmittedByInput[] + connectOrCreate?: Prisma.TicketCreateOrConnectWithoutSubmittedByInput | Prisma.TicketCreateOrConnectWithoutSubmittedByInput[] + createMany?: Prisma.TicketCreateManySubmittedByInputEnvelope + connect?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] +} + +export type TicketUncheckedCreateNestedManyWithoutAssignedToInput = { + create?: Prisma.XOR | Prisma.TicketCreateWithoutAssignedToInput[] | Prisma.TicketUncheckedCreateWithoutAssignedToInput[] + connectOrCreate?: Prisma.TicketCreateOrConnectWithoutAssignedToInput | Prisma.TicketCreateOrConnectWithoutAssignedToInput[] + createMany?: Prisma.TicketCreateManyAssignedToInputEnvelope + connect?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] +} + +export type TicketUpdateManyWithoutSubmittedByNestedInput = { + create?: Prisma.XOR | Prisma.TicketCreateWithoutSubmittedByInput[] | Prisma.TicketUncheckedCreateWithoutSubmittedByInput[] + connectOrCreate?: Prisma.TicketCreateOrConnectWithoutSubmittedByInput | Prisma.TicketCreateOrConnectWithoutSubmittedByInput[] + upsert?: Prisma.TicketUpsertWithWhereUniqueWithoutSubmittedByInput | Prisma.TicketUpsertWithWhereUniqueWithoutSubmittedByInput[] + createMany?: Prisma.TicketCreateManySubmittedByInputEnvelope + set?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] + disconnect?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] + delete?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] + connect?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] + update?: Prisma.TicketUpdateWithWhereUniqueWithoutSubmittedByInput | Prisma.TicketUpdateWithWhereUniqueWithoutSubmittedByInput[] + updateMany?: Prisma.TicketUpdateManyWithWhereWithoutSubmittedByInput | Prisma.TicketUpdateManyWithWhereWithoutSubmittedByInput[] + deleteMany?: Prisma.TicketScalarWhereInput | Prisma.TicketScalarWhereInput[] +} + +export type TicketUpdateManyWithoutAssignedToNestedInput = { + create?: Prisma.XOR | Prisma.TicketCreateWithoutAssignedToInput[] | Prisma.TicketUncheckedCreateWithoutAssignedToInput[] + connectOrCreate?: Prisma.TicketCreateOrConnectWithoutAssignedToInput | Prisma.TicketCreateOrConnectWithoutAssignedToInput[] + upsert?: Prisma.TicketUpsertWithWhereUniqueWithoutAssignedToInput | Prisma.TicketUpsertWithWhereUniqueWithoutAssignedToInput[] + createMany?: Prisma.TicketCreateManyAssignedToInputEnvelope + set?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] + disconnect?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] + delete?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] + connect?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] + update?: Prisma.TicketUpdateWithWhereUniqueWithoutAssignedToInput | Prisma.TicketUpdateWithWhereUniqueWithoutAssignedToInput[] + updateMany?: Prisma.TicketUpdateManyWithWhereWithoutAssignedToInput | Prisma.TicketUpdateManyWithWhereWithoutAssignedToInput[] + deleteMany?: Prisma.TicketScalarWhereInput | Prisma.TicketScalarWhereInput[] +} + +export type TicketUncheckedUpdateManyWithoutSubmittedByNestedInput = { + create?: Prisma.XOR | Prisma.TicketCreateWithoutSubmittedByInput[] | Prisma.TicketUncheckedCreateWithoutSubmittedByInput[] + connectOrCreate?: Prisma.TicketCreateOrConnectWithoutSubmittedByInput | Prisma.TicketCreateOrConnectWithoutSubmittedByInput[] + upsert?: Prisma.TicketUpsertWithWhereUniqueWithoutSubmittedByInput | Prisma.TicketUpsertWithWhereUniqueWithoutSubmittedByInput[] + createMany?: Prisma.TicketCreateManySubmittedByInputEnvelope + set?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] + disconnect?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] + delete?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] + connect?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] + update?: Prisma.TicketUpdateWithWhereUniqueWithoutSubmittedByInput | Prisma.TicketUpdateWithWhereUniqueWithoutSubmittedByInput[] + updateMany?: Prisma.TicketUpdateManyWithWhereWithoutSubmittedByInput | Prisma.TicketUpdateManyWithWhereWithoutSubmittedByInput[] + deleteMany?: Prisma.TicketScalarWhereInput | Prisma.TicketScalarWhereInput[] +} + +export type TicketUncheckedUpdateManyWithoutAssignedToNestedInput = { + create?: Prisma.XOR | Prisma.TicketCreateWithoutAssignedToInput[] | Prisma.TicketUncheckedCreateWithoutAssignedToInput[] + connectOrCreate?: Prisma.TicketCreateOrConnectWithoutAssignedToInput | Prisma.TicketCreateOrConnectWithoutAssignedToInput[] + upsert?: Prisma.TicketUpsertWithWhereUniqueWithoutAssignedToInput | Prisma.TicketUpsertWithWhereUniqueWithoutAssignedToInput[] + createMany?: Prisma.TicketCreateManyAssignedToInputEnvelope + set?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] + disconnect?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] + delete?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] + connect?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] + update?: Prisma.TicketUpdateWithWhereUniqueWithoutAssignedToInput | Prisma.TicketUpdateWithWhereUniqueWithoutAssignedToInput[] + updateMany?: Prisma.TicketUpdateManyWithWhereWithoutAssignedToInput | Prisma.TicketUpdateManyWithWhereWithoutAssignedToInput[] + deleteMany?: Prisma.TicketScalarWhereInput | Prisma.TicketScalarWhereInput[] +} + +export type TicketCreateNestedManyWithoutScanInput = { + create?: Prisma.XOR | Prisma.TicketCreateWithoutScanInput[] | Prisma.TicketUncheckedCreateWithoutScanInput[] + connectOrCreate?: Prisma.TicketCreateOrConnectWithoutScanInput | Prisma.TicketCreateOrConnectWithoutScanInput[] + createMany?: Prisma.TicketCreateManyScanInputEnvelope + connect?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] +} + +export type TicketCreateNestedManyWithoutReanalysisScanInput = { + create?: Prisma.XOR | Prisma.TicketCreateWithoutReanalysisScanInput[] | Prisma.TicketUncheckedCreateWithoutReanalysisScanInput[] + connectOrCreate?: Prisma.TicketCreateOrConnectWithoutReanalysisScanInput | Prisma.TicketCreateOrConnectWithoutReanalysisScanInput[] + createMany?: Prisma.TicketCreateManyReanalysisScanInputEnvelope + connect?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] +} + +export type TicketUncheckedCreateNestedManyWithoutScanInput = { + create?: Prisma.XOR | Prisma.TicketCreateWithoutScanInput[] | Prisma.TicketUncheckedCreateWithoutScanInput[] + connectOrCreate?: Prisma.TicketCreateOrConnectWithoutScanInput | Prisma.TicketCreateOrConnectWithoutScanInput[] + createMany?: Prisma.TicketCreateManyScanInputEnvelope + connect?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] +} + +export type TicketUncheckedCreateNestedManyWithoutReanalysisScanInput = { + create?: Prisma.XOR | Prisma.TicketCreateWithoutReanalysisScanInput[] | Prisma.TicketUncheckedCreateWithoutReanalysisScanInput[] + connectOrCreate?: Prisma.TicketCreateOrConnectWithoutReanalysisScanInput | Prisma.TicketCreateOrConnectWithoutReanalysisScanInput[] + createMany?: Prisma.TicketCreateManyReanalysisScanInputEnvelope + connect?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] +} + +export type TicketUpdateManyWithoutScanNestedInput = { + create?: Prisma.XOR | Prisma.TicketCreateWithoutScanInput[] | Prisma.TicketUncheckedCreateWithoutScanInput[] + connectOrCreate?: Prisma.TicketCreateOrConnectWithoutScanInput | Prisma.TicketCreateOrConnectWithoutScanInput[] + upsert?: Prisma.TicketUpsertWithWhereUniqueWithoutScanInput | Prisma.TicketUpsertWithWhereUniqueWithoutScanInput[] + createMany?: Prisma.TicketCreateManyScanInputEnvelope + set?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] + disconnect?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] + delete?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] + connect?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] + update?: Prisma.TicketUpdateWithWhereUniqueWithoutScanInput | Prisma.TicketUpdateWithWhereUniqueWithoutScanInput[] + updateMany?: Prisma.TicketUpdateManyWithWhereWithoutScanInput | Prisma.TicketUpdateManyWithWhereWithoutScanInput[] + deleteMany?: Prisma.TicketScalarWhereInput | Prisma.TicketScalarWhereInput[] +} + +export type TicketUpdateManyWithoutReanalysisScanNestedInput = { + create?: Prisma.XOR | Prisma.TicketCreateWithoutReanalysisScanInput[] | Prisma.TicketUncheckedCreateWithoutReanalysisScanInput[] + connectOrCreate?: Prisma.TicketCreateOrConnectWithoutReanalysisScanInput | Prisma.TicketCreateOrConnectWithoutReanalysisScanInput[] + upsert?: Prisma.TicketUpsertWithWhereUniqueWithoutReanalysisScanInput | Prisma.TicketUpsertWithWhereUniqueWithoutReanalysisScanInput[] + createMany?: Prisma.TicketCreateManyReanalysisScanInputEnvelope + set?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] + disconnect?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] + delete?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] + connect?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] + update?: Prisma.TicketUpdateWithWhereUniqueWithoutReanalysisScanInput | Prisma.TicketUpdateWithWhereUniqueWithoutReanalysisScanInput[] + updateMany?: Prisma.TicketUpdateManyWithWhereWithoutReanalysisScanInput | Prisma.TicketUpdateManyWithWhereWithoutReanalysisScanInput[] + deleteMany?: Prisma.TicketScalarWhereInput | Prisma.TicketScalarWhereInput[] +} + +export type TicketUncheckedUpdateManyWithoutScanNestedInput = { + create?: Prisma.XOR | Prisma.TicketCreateWithoutScanInput[] | Prisma.TicketUncheckedCreateWithoutScanInput[] + connectOrCreate?: Prisma.TicketCreateOrConnectWithoutScanInput | Prisma.TicketCreateOrConnectWithoutScanInput[] + upsert?: Prisma.TicketUpsertWithWhereUniqueWithoutScanInput | Prisma.TicketUpsertWithWhereUniqueWithoutScanInput[] + createMany?: Prisma.TicketCreateManyScanInputEnvelope + set?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] + disconnect?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] + delete?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] + connect?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] + update?: Prisma.TicketUpdateWithWhereUniqueWithoutScanInput | Prisma.TicketUpdateWithWhereUniqueWithoutScanInput[] + updateMany?: Prisma.TicketUpdateManyWithWhereWithoutScanInput | Prisma.TicketUpdateManyWithWhereWithoutScanInput[] + deleteMany?: Prisma.TicketScalarWhereInput | Prisma.TicketScalarWhereInput[] +} + +export type TicketUncheckedUpdateManyWithoutReanalysisScanNestedInput = { + create?: Prisma.XOR | Prisma.TicketCreateWithoutReanalysisScanInput[] | Prisma.TicketUncheckedCreateWithoutReanalysisScanInput[] + connectOrCreate?: Prisma.TicketCreateOrConnectWithoutReanalysisScanInput | Prisma.TicketCreateOrConnectWithoutReanalysisScanInput[] + upsert?: Prisma.TicketUpsertWithWhereUniqueWithoutReanalysisScanInput | Prisma.TicketUpsertWithWhereUniqueWithoutReanalysisScanInput[] + createMany?: Prisma.TicketCreateManyReanalysisScanInputEnvelope + set?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] + disconnect?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] + delete?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] + connect?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] + update?: Prisma.TicketUpdateWithWhereUniqueWithoutReanalysisScanInput | Prisma.TicketUpdateWithWhereUniqueWithoutReanalysisScanInput[] + updateMany?: Prisma.TicketUpdateManyWithWhereWithoutReanalysisScanInput | Prisma.TicketUpdateManyWithWhereWithoutReanalysisScanInput[] + deleteMany?: Prisma.TicketScalarWhereInput | Prisma.TicketScalarWhereInput[] +} + +export type TicketCreateNestedManyWithoutReportInput = { + create?: Prisma.XOR | Prisma.TicketCreateWithoutReportInput[] | Prisma.TicketUncheckedCreateWithoutReportInput[] + connectOrCreate?: Prisma.TicketCreateOrConnectWithoutReportInput | Prisma.TicketCreateOrConnectWithoutReportInput[] + createMany?: Prisma.TicketCreateManyReportInputEnvelope + connect?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] +} + +export type TicketCreateNestedManyWithoutReanalysisReportInput = { + create?: Prisma.XOR | Prisma.TicketCreateWithoutReanalysisReportInput[] | Prisma.TicketUncheckedCreateWithoutReanalysisReportInput[] + connectOrCreate?: Prisma.TicketCreateOrConnectWithoutReanalysisReportInput | Prisma.TicketCreateOrConnectWithoutReanalysisReportInput[] + createMany?: Prisma.TicketCreateManyReanalysisReportInputEnvelope + connect?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] +} + +export type TicketUncheckedCreateNestedManyWithoutReportInput = { + create?: Prisma.XOR | Prisma.TicketCreateWithoutReportInput[] | Prisma.TicketUncheckedCreateWithoutReportInput[] + connectOrCreate?: Prisma.TicketCreateOrConnectWithoutReportInput | Prisma.TicketCreateOrConnectWithoutReportInput[] + createMany?: Prisma.TicketCreateManyReportInputEnvelope + connect?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] +} + +export type TicketUncheckedCreateNestedManyWithoutReanalysisReportInput = { + create?: Prisma.XOR | Prisma.TicketCreateWithoutReanalysisReportInput[] | Prisma.TicketUncheckedCreateWithoutReanalysisReportInput[] + connectOrCreate?: Prisma.TicketCreateOrConnectWithoutReanalysisReportInput | Prisma.TicketCreateOrConnectWithoutReanalysisReportInput[] + createMany?: Prisma.TicketCreateManyReanalysisReportInputEnvelope + connect?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] +} + +export type TicketUpdateManyWithoutReportNestedInput = { + create?: Prisma.XOR | Prisma.TicketCreateWithoutReportInput[] | Prisma.TicketUncheckedCreateWithoutReportInput[] + connectOrCreate?: Prisma.TicketCreateOrConnectWithoutReportInput | Prisma.TicketCreateOrConnectWithoutReportInput[] + upsert?: Prisma.TicketUpsertWithWhereUniqueWithoutReportInput | Prisma.TicketUpsertWithWhereUniqueWithoutReportInput[] + createMany?: Prisma.TicketCreateManyReportInputEnvelope + set?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] + disconnect?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] + delete?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] + connect?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] + update?: Prisma.TicketUpdateWithWhereUniqueWithoutReportInput | Prisma.TicketUpdateWithWhereUniqueWithoutReportInput[] + updateMany?: Prisma.TicketUpdateManyWithWhereWithoutReportInput | Prisma.TicketUpdateManyWithWhereWithoutReportInput[] + deleteMany?: Prisma.TicketScalarWhereInput | Prisma.TicketScalarWhereInput[] +} + +export type TicketUpdateManyWithoutReanalysisReportNestedInput = { + create?: Prisma.XOR | Prisma.TicketCreateWithoutReanalysisReportInput[] | Prisma.TicketUncheckedCreateWithoutReanalysisReportInput[] + connectOrCreate?: Prisma.TicketCreateOrConnectWithoutReanalysisReportInput | Prisma.TicketCreateOrConnectWithoutReanalysisReportInput[] + upsert?: Prisma.TicketUpsertWithWhereUniqueWithoutReanalysisReportInput | Prisma.TicketUpsertWithWhereUniqueWithoutReanalysisReportInput[] + createMany?: Prisma.TicketCreateManyReanalysisReportInputEnvelope + set?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] + disconnect?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] + delete?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] + connect?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] + update?: Prisma.TicketUpdateWithWhereUniqueWithoutReanalysisReportInput | Prisma.TicketUpdateWithWhereUniqueWithoutReanalysisReportInput[] + updateMany?: Prisma.TicketUpdateManyWithWhereWithoutReanalysisReportInput | Prisma.TicketUpdateManyWithWhereWithoutReanalysisReportInput[] + deleteMany?: Prisma.TicketScalarWhereInput | Prisma.TicketScalarWhereInput[] +} + +export type TicketUncheckedUpdateManyWithoutReportNestedInput = { + create?: Prisma.XOR | Prisma.TicketCreateWithoutReportInput[] | Prisma.TicketUncheckedCreateWithoutReportInput[] + connectOrCreate?: Prisma.TicketCreateOrConnectWithoutReportInput | Prisma.TicketCreateOrConnectWithoutReportInput[] + upsert?: Prisma.TicketUpsertWithWhereUniqueWithoutReportInput | Prisma.TicketUpsertWithWhereUniqueWithoutReportInput[] + createMany?: Prisma.TicketCreateManyReportInputEnvelope + set?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] + disconnect?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] + delete?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] + connect?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] + update?: Prisma.TicketUpdateWithWhereUniqueWithoutReportInput | Prisma.TicketUpdateWithWhereUniqueWithoutReportInput[] + updateMany?: Prisma.TicketUpdateManyWithWhereWithoutReportInput | Prisma.TicketUpdateManyWithWhereWithoutReportInput[] + deleteMany?: Prisma.TicketScalarWhereInput | Prisma.TicketScalarWhereInput[] +} + +export type TicketUncheckedUpdateManyWithoutReanalysisReportNestedInput = { + create?: Prisma.XOR | Prisma.TicketCreateWithoutReanalysisReportInput[] | Prisma.TicketUncheckedCreateWithoutReanalysisReportInput[] + connectOrCreate?: Prisma.TicketCreateOrConnectWithoutReanalysisReportInput | Prisma.TicketCreateOrConnectWithoutReanalysisReportInput[] + upsert?: Prisma.TicketUpsertWithWhereUniqueWithoutReanalysisReportInput | Prisma.TicketUpsertWithWhereUniqueWithoutReanalysisReportInput[] + createMany?: Prisma.TicketCreateManyReanalysisReportInputEnvelope + set?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] + disconnect?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] + delete?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] + connect?: Prisma.TicketWhereUniqueInput | Prisma.TicketWhereUniqueInput[] + update?: Prisma.TicketUpdateWithWhereUniqueWithoutReanalysisReportInput | Prisma.TicketUpdateWithWhereUniqueWithoutReanalysisReportInput[] + updateMany?: Prisma.TicketUpdateManyWithWhereWithoutReanalysisReportInput | Prisma.TicketUpdateManyWithWhereWithoutReanalysisReportInput[] + deleteMany?: Prisma.TicketScalarWhereInput | Prisma.TicketScalarWhereInput[] +} + +export type EnumTicketTypeFieldUpdateOperationsInput = { + set?: $Enums.TicketType +} + +export type EnumTicketStatusFieldUpdateOperationsInput = { + set?: $Enums.TicketStatus +} + +export type EnumTicketPriorityFieldUpdateOperationsInput = { + set?: $Enums.TicketPriority +} + +export type TicketCreateWithoutSubmittedByInput = { + id?: string + code: string + type: $Enums.TicketType + status?: $Enums.TicketStatus + priority?: $Enums.TicketPriority + reason: string + resolutionNote?: string | null + createdAt?: Date | string + updatedAt?: Date | string + resolvedAt?: Date | string | null + scan?: Prisma.ScanCreateNestedOneWithoutTicketsForScanInput + report?: Prisma.ReportCreateNestedOneWithoutTicketsForReportInput + assignedTo?: Prisma.UserCreateNestedOneWithoutAssignedTicketsInput + reanalysisScan?: Prisma.ScanCreateNestedOneWithoutTicketsAsReanalysisInput + reanalysisReport?: Prisma.ReportCreateNestedOneWithoutTicketsAsReanalysisInput +} + +export type TicketUncheckedCreateWithoutSubmittedByInput = { + id?: string + code: string + type: $Enums.TicketType + status?: $Enums.TicketStatus + priority?: $Enums.TicketPriority + reason: string + scanId?: string | null + reportId?: string | null + assignedToId?: string | null + resolutionNote?: string | null + reanalysisScanId?: string | null + reanalysisReportId?: string | null + createdAt?: Date | string + updatedAt?: Date | string + resolvedAt?: Date | string | null +} + +export type TicketCreateOrConnectWithoutSubmittedByInput = { + where: Prisma.TicketWhereUniqueInput + create: Prisma.XOR +} + +export type TicketCreateManySubmittedByInputEnvelope = { + data: Prisma.TicketCreateManySubmittedByInput | Prisma.TicketCreateManySubmittedByInput[] + skipDuplicates?: boolean +} + +export type TicketCreateWithoutAssignedToInput = { + id?: string + code: string + type: $Enums.TicketType + status?: $Enums.TicketStatus + priority?: $Enums.TicketPriority + reason: string + resolutionNote?: string | null + createdAt?: Date | string + updatedAt?: Date | string + resolvedAt?: Date | string | null + scan?: Prisma.ScanCreateNestedOneWithoutTicketsForScanInput + report?: Prisma.ReportCreateNestedOneWithoutTicketsForReportInput + submittedBy: Prisma.UserCreateNestedOneWithoutSubmittedTicketsInput + reanalysisScan?: Prisma.ScanCreateNestedOneWithoutTicketsAsReanalysisInput + reanalysisReport?: Prisma.ReportCreateNestedOneWithoutTicketsAsReanalysisInput +} + +export type TicketUncheckedCreateWithoutAssignedToInput = { + id?: string + code: string + type: $Enums.TicketType + status?: $Enums.TicketStatus + priority?: $Enums.TicketPriority + reason: string + scanId?: string | null + reportId?: string | null + submittedById: string + resolutionNote?: string | null + reanalysisScanId?: string | null + reanalysisReportId?: string | null + createdAt?: Date | string + updatedAt?: Date | string + resolvedAt?: Date | string | null +} + +export type TicketCreateOrConnectWithoutAssignedToInput = { + where: Prisma.TicketWhereUniqueInput + create: Prisma.XOR +} + +export type TicketCreateManyAssignedToInputEnvelope = { + data: Prisma.TicketCreateManyAssignedToInput | Prisma.TicketCreateManyAssignedToInput[] + skipDuplicates?: boolean +} + +export type TicketUpsertWithWhereUniqueWithoutSubmittedByInput = { + where: Prisma.TicketWhereUniqueInput + update: Prisma.XOR + create: Prisma.XOR +} + +export type TicketUpdateWithWhereUniqueWithoutSubmittedByInput = { + where: Prisma.TicketWhereUniqueInput + data: Prisma.XOR +} + +export type TicketUpdateManyWithWhereWithoutSubmittedByInput = { + where: Prisma.TicketScalarWhereInput + data: Prisma.XOR +} + +export type TicketScalarWhereInput = { + AND?: Prisma.TicketScalarWhereInput | Prisma.TicketScalarWhereInput[] + OR?: Prisma.TicketScalarWhereInput[] + NOT?: Prisma.TicketScalarWhereInput | Prisma.TicketScalarWhereInput[] + id?: Prisma.StringFilter<"Ticket"> | string + code?: Prisma.StringFilter<"Ticket"> | string + type?: Prisma.EnumTicketTypeFilter<"Ticket"> | $Enums.TicketType + status?: Prisma.EnumTicketStatusFilter<"Ticket"> | $Enums.TicketStatus + priority?: Prisma.EnumTicketPriorityFilter<"Ticket"> | $Enums.TicketPriority + reason?: Prisma.StringFilter<"Ticket"> | string + scanId?: Prisma.StringNullableFilter<"Ticket"> | string | null + reportId?: Prisma.StringNullableFilter<"Ticket"> | string | null + submittedById?: Prisma.StringFilter<"Ticket"> | string + assignedToId?: Prisma.StringNullableFilter<"Ticket"> | string | null + resolutionNote?: Prisma.StringNullableFilter<"Ticket"> | string | null + reanalysisScanId?: Prisma.StringNullableFilter<"Ticket"> | string | null + reanalysisReportId?: Prisma.StringNullableFilter<"Ticket"> | string | null + createdAt?: Prisma.DateTimeFilter<"Ticket"> | Date | string + updatedAt?: Prisma.DateTimeFilter<"Ticket"> | Date | string + resolvedAt?: Prisma.DateTimeNullableFilter<"Ticket"> | Date | string | null +} + +export type TicketUpsertWithWhereUniqueWithoutAssignedToInput = { + where: Prisma.TicketWhereUniqueInput + update: Prisma.XOR + create: Prisma.XOR +} + +export type TicketUpdateWithWhereUniqueWithoutAssignedToInput = { + where: Prisma.TicketWhereUniqueInput + data: Prisma.XOR +} + +export type TicketUpdateManyWithWhereWithoutAssignedToInput = { + where: Prisma.TicketScalarWhereInput + data: Prisma.XOR +} + +export type TicketCreateWithoutScanInput = { + id?: string + code: string + type: $Enums.TicketType + status?: $Enums.TicketStatus + priority?: $Enums.TicketPriority + reason: string + resolutionNote?: string | null + createdAt?: Date | string + updatedAt?: Date | string + resolvedAt?: Date | string | null + report?: Prisma.ReportCreateNestedOneWithoutTicketsForReportInput + submittedBy: Prisma.UserCreateNestedOneWithoutSubmittedTicketsInput + assignedTo?: Prisma.UserCreateNestedOneWithoutAssignedTicketsInput + reanalysisScan?: Prisma.ScanCreateNestedOneWithoutTicketsAsReanalysisInput + reanalysisReport?: Prisma.ReportCreateNestedOneWithoutTicketsAsReanalysisInput +} + +export type TicketUncheckedCreateWithoutScanInput = { + id?: string + code: string + type: $Enums.TicketType + status?: $Enums.TicketStatus + priority?: $Enums.TicketPriority + reason: string + reportId?: string | null + submittedById: string + assignedToId?: string | null + resolutionNote?: string | null + reanalysisScanId?: string | null + reanalysisReportId?: string | null + createdAt?: Date | string + updatedAt?: Date | string + resolvedAt?: Date | string | null +} + +export type TicketCreateOrConnectWithoutScanInput = { + where: Prisma.TicketWhereUniqueInput + create: Prisma.XOR +} + +export type TicketCreateManyScanInputEnvelope = { + data: Prisma.TicketCreateManyScanInput | Prisma.TicketCreateManyScanInput[] + skipDuplicates?: boolean +} + +export type TicketCreateWithoutReanalysisScanInput = { + id?: string + code: string + type: $Enums.TicketType + status?: $Enums.TicketStatus + priority?: $Enums.TicketPriority + reason: string + resolutionNote?: string | null + createdAt?: Date | string + updatedAt?: Date | string + resolvedAt?: Date | string | null + scan?: Prisma.ScanCreateNestedOneWithoutTicketsForScanInput + report?: Prisma.ReportCreateNestedOneWithoutTicketsForReportInput + submittedBy: Prisma.UserCreateNestedOneWithoutSubmittedTicketsInput + assignedTo?: Prisma.UserCreateNestedOneWithoutAssignedTicketsInput + reanalysisReport?: Prisma.ReportCreateNestedOneWithoutTicketsAsReanalysisInput +} + +export type TicketUncheckedCreateWithoutReanalysisScanInput = { + id?: string + code: string + type: $Enums.TicketType + status?: $Enums.TicketStatus + priority?: $Enums.TicketPriority + reason: string + scanId?: string | null + reportId?: string | null + submittedById: string + assignedToId?: string | null + resolutionNote?: string | null + reanalysisReportId?: string | null + createdAt?: Date | string + updatedAt?: Date | string + resolvedAt?: Date | string | null +} + +export type TicketCreateOrConnectWithoutReanalysisScanInput = { + where: Prisma.TicketWhereUniqueInput + create: Prisma.XOR +} + +export type TicketCreateManyReanalysisScanInputEnvelope = { + data: Prisma.TicketCreateManyReanalysisScanInput | Prisma.TicketCreateManyReanalysisScanInput[] + skipDuplicates?: boolean +} + +export type TicketUpsertWithWhereUniqueWithoutScanInput = { + where: Prisma.TicketWhereUniqueInput + update: Prisma.XOR + create: Prisma.XOR +} + +export type TicketUpdateWithWhereUniqueWithoutScanInput = { + where: Prisma.TicketWhereUniqueInput + data: Prisma.XOR +} + +export type TicketUpdateManyWithWhereWithoutScanInput = { + where: Prisma.TicketScalarWhereInput + data: Prisma.XOR +} + +export type TicketUpsertWithWhereUniqueWithoutReanalysisScanInput = { + where: Prisma.TicketWhereUniqueInput + update: Prisma.XOR + create: Prisma.XOR +} + +export type TicketUpdateWithWhereUniqueWithoutReanalysisScanInput = { + where: Prisma.TicketWhereUniqueInput + data: Prisma.XOR +} + +export type TicketUpdateManyWithWhereWithoutReanalysisScanInput = { + where: Prisma.TicketScalarWhereInput + data: Prisma.XOR +} + +export type TicketCreateWithoutReportInput = { + id?: string + code: string + type: $Enums.TicketType + status?: $Enums.TicketStatus + priority?: $Enums.TicketPriority + reason: string + resolutionNote?: string | null + createdAt?: Date | string + updatedAt?: Date | string + resolvedAt?: Date | string | null + scan?: Prisma.ScanCreateNestedOneWithoutTicketsForScanInput + submittedBy: Prisma.UserCreateNestedOneWithoutSubmittedTicketsInput + assignedTo?: Prisma.UserCreateNestedOneWithoutAssignedTicketsInput + reanalysisScan?: Prisma.ScanCreateNestedOneWithoutTicketsAsReanalysisInput + reanalysisReport?: Prisma.ReportCreateNestedOneWithoutTicketsAsReanalysisInput +} + +export type TicketUncheckedCreateWithoutReportInput = { + id?: string + code: string + type: $Enums.TicketType + status?: $Enums.TicketStatus + priority?: $Enums.TicketPriority + reason: string + scanId?: string | null + submittedById: string + assignedToId?: string | null + resolutionNote?: string | null + reanalysisScanId?: string | null + reanalysisReportId?: string | null + createdAt?: Date | string + updatedAt?: Date | string + resolvedAt?: Date | string | null +} + +export type TicketCreateOrConnectWithoutReportInput = { + where: Prisma.TicketWhereUniqueInput + create: Prisma.XOR +} + +export type TicketCreateManyReportInputEnvelope = { + data: Prisma.TicketCreateManyReportInput | Prisma.TicketCreateManyReportInput[] + skipDuplicates?: boolean +} + +export type TicketCreateWithoutReanalysisReportInput = { + id?: string + code: string + type: $Enums.TicketType + status?: $Enums.TicketStatus + priority?: $Enums.TicketPriority + reason: string + resolutionNote?: string | null + createdAt?: Date | string + updatedAt?: Date | string + resolvedAt?: Date | string | null + scan?: Prisma.ScanCreateNestedOneWithoutTicketsForScanInput + report?: Prisma.ReportCreateNestedOneWithoutTicketsForReportInput + submittedBy: Prisma.UserCreateNestedOneWithoutSubmittedTicketsInput + assignedTo?: Prisma.UserCreateNestedOneWithoutAssignedTicketsInput + reanalysisScan?: Prisma.ScanCreateNestedOneWithoutTicketsAsReanalysisInput +} + +export type TicketUncheckedCreateWithoutReanalysisReportInput = { + id?: string + code: string + type: $Enums.TicketType + status?: $Enums.TicketStatus + priority?: $Enums.TicketPriority + reason: string + scanId?: string | null + reportId?: string | null + submittedById: string + assignedToId?: string | null + resolutionNote?: string | null + reanalysisScanId?: string | null + createdAt?: Date | string + updatedAt?: Date | string + resolvedAt?: Date | string | null +} + +export type TicketCreateOrConnectWithoutReanalysisReportInput = { + where: Prisma.TicketWhereUniqueInput + create: Prisma.XOR +} + +export type TicketCreateManyReanalysisReportInputEnvelope = { + data: Prisma.TicketCreateManyReanalysisReportInput | Prisma.TicketCreateManyReanalysisReportInput[] + skipDuplicates?: boolean +} + +export type TicketUpsertWithWhereUniqueWithoutReportInput = { + where: Prisma.TicketWhereUniqueInput + update: Prisma.XOR + create: Prisma.XOR +} + +export type TicketUpdateWithWhereUniqueWithoutReportInput = { + where: Prisma.TicketWhereUniqueInput + data: Prisma.XOR +} + +export type TicketUpdateManyWithWhereWithoutReportInput = { + where: Prisma.TicketScalarWhereInput + data: Prisma.XOR +} + +export type TicketUpsertWithWhereUniqueWithoutReanalysisReportInput = { + where: Prisma.TicketWhereUniqueInput + update: Prisma.XOR + create: Prisma.XOR +} + +export type TicketUpdateWithWhereUniqueWithoutReanalysisReportInput = { + where: Prisma.TicketWhereUniqueInput + data: Prisma.XOR +} + +export type TicketUpdateManyWithWhereWithoutReanalysisReportInput = { + where: Prisma.TicketScalarWhereInput + data: Prisma.XOR +} + +export type TicketCreateManySubmittedByInput = { + id?: string + code: string + type: $Enums.TicketType + status?: $Enums.TicketStatus + priority?: $Enums.TicketPriority + reason: string + scanId?: string | null + reportId?: string | null + assignedToId?: string | null + resolutionNote?: string | null + reanalysisScanId?: string | null + reanalysisReportId?: string | null + createdAt?: Date | string + updatedAt?: Date | string + resolvedAt?: Date | string | null +} + +export type TicketCreateManyAssignedToInput = { + id?: string + code: string + type: $Enums.TicketType + status?: $Enums.TicketStatus + priority?: $Enums.TicketPriority + reason: string + scanId?: string | null + reportId?: string | null + submittedById: string + resolutionNote?: string | null + reanalysisScanId?: string | null + reanalysisReportId?: string | null + createdAt?: Date | string + updatedAt?: Date | string + resolvedAt?: Date | string | null +} + +export type TicketUpdateWithoutSubmittedByInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + code?: Prisma.StringFieldUpdateOperationsInput | string + type?: Prisma.EnumTicketTypeFieldUpdateOperationsInput | $Enums.TicketType + status?: Prisma.EnumTicketStatusFieldUpdateOperationsInput | $Enums.TicketStatus + priority?: Prisma.EnumTicketPriorityFieldUpdateOperationsInput | $Enums.TicketPriority + reason?: Prisma.StringFieldUpdateOperationsInput | string + resolutionNote?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + resolvedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null + scan?: Prisma.ScanUpdateOneWithoutTicketsForScanNestedInput + report?: Prisma.ReportUpdateOneWithoutTicketsForReportNestedInput + assignedTo?: Prisma.UserUpdateOneWithoutAssignedTicketsNestedInput + reanalysisScan?: Prisma.ScanUpdateOneWithoutTicketsAsReanalysisNestedInput + reanalysisReport?: Prisma.ReportUpdateOneWithoutTicketsAsReanalysisNestedInput +} + +export type TicketUncheckedUpdateWithoutSubmittedByInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + code?: Prisma.StringFieldUpdateOperationsInput | string + type?: Prisma.EnumTicketTypeFieldUpdateOperationsInput | $Enums.TicketType + status?: Prisma.EnumTicketStatusFieldUpdateOperationsInput | $Enums.TicketStatus + priority?: Prisma.EnumTicketPriorityFieldUpdateOperationsInput | $Enums.TicketPriority + reason?: Prisma.StringFieldUpdateOperationsInput | string + scanId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + reportId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + assignedToId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + resolutionNote?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + reanalysisScanId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + reanalysisReportId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + resolvedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null +} + +export type TicketUncheckedUpdateManyWithoutSubmittedByInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + code?: Prisma.StringFieldUpdateOperationsInput | string + type?: Prisma.EnumTicketTypeFieldUpdateOperationsInput | $Enums.TicketType + status?: Prisma.EnumTicketStatusFieldUpdateOperationsInput | $Enums.TicketStatus + priority?: Prisma.EnumTicketPriorityFieldUpdateOperationsInput | $Enums.TicketPriority + reason?: Prisma.StringFieldUpdateOperationsInput | string + scanId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + reportId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + assignedToId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + resolutionNote?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + reanalysisScanId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + reanalysisReportId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + resolvedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null +} + +export type TicketUpdateWithoutAssignedToInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + code?: Prisma.StringFieldUpdateOperationsInput | string + type?: Prisma.EnumTicketTypeFieldUpdateOperationsInput | $Enums.TicketType + status?: Prisma.EnumTicketStatusFieldUpdateOperationsInput | $Enums.TicketStatus + priority?: Prisma.EnumTicketPriorityFieldUpdateOperationsInput | $Enums.TicketPriority + reason?: Prisma.StringFieldUpdateOperationsInput | string + resolutionNote?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + resolvedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null + scan?: Prisma.ScanUpdateOneWithoutTicketsForScanNestedInput + report?: Prisma.ReportUpdateOneWithoutTicketsForReportNestedInput + submittedBy?: Prisma.UserUpdateOneRequiredWithoutSubmittedTicketsNestedInput + reanalysisScan?: Prisma.ScanUpdateOneWithoutTicketsAsReanalysisNestedInput + reanalysisReport?: Prisma.ReportUpdateOneWithoutTicketsAsReanalysisNestedInput +} + +export type TicketUncheckedUpdateWithoutAssignedToInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + code?: Prisma.StringFieldUpdateOperationsInput | string + type?: Prisma.EnumTicketTypeFieldUpdateOperationsInput | $Enums.TicketType + status?: Prisma.EnumTicketStatusFieldUpdateOperationsInput | $Enums.TicketStatus + priority?: Prisma.EnumTicketPriorityFieldUpdateOperationsInput | $Enums.TicketPriority + reason?: Prisma.StringFieldUpdateOperationsInput | string + scanId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + reportId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + submittedById?: Prisma.StringFieldUpdateOperationsInput | string + resolutionNote?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + reanalysisScanId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + reanalysisReportId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + resolvedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null +} + +export type TicketUncheckedUpdateManyWithoutAssignedToInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + code?: Prisma.StringFieldUpdateOperationsInput | string + type?: Prisma.EnumTicketTypeFieldUpdateOperationsInput | $Enums.TicketType + status?: Prisma.EnumTicketStatusFieldUpdateOperationsInput | $Enums.TicketStatus + priority?: Prisma.EnumTicketPriorityFieldUpdateOperationsInput | $Enums.TicketPriority + reason?: Prisma.StringFieldUpdateOperationsInput | string + scanId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + reportId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + submittedById?: Prisma.StringFieldUpdateOperationsInput | string + resolutionNote?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + reanalysisScanId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + reanalysisReportId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + resolvedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null +} + +export type TicketCreateManyScanInput = { + id?: string + code: string + type: $Enums.TicketType + status?: $Enums.TicketStatus + priority?: $Enums.TicketPriority + reason: string + reportId?: string | null + submittedById: string + assignedToId?: string | null + resolutionNote?: string | null + reanalysisScanId?: string | null + reanalysisReportId?: string | null + createdAt?: Date | string + updatedAt?: Date | string + resolvedAt?: Date | string | null +} + +export type TicketCreateManyReanalysisScanInput = { + id?: string + code: string + type: $Enums.TicketType + status?: $Enums.TicketStatus + priority?: $Enums.TicketPriority + reason: string + scanId?: string | null + reportId?: string | null + submittedById: string + assignedToId?: string | null + resolutionNote?: string | null + reanalysisReportId?: string | null + createdAt?: Date | string + updatedAt?: Date | string + resolvedAt?: Date | string | null +} + +export type TicketUpdateWithoutScanInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + code?: Prisma.StringFieldUpdateOperationsInput | string + type?: Prisma.EnumTicketTypeFieldUpdateOperationsInput | $Enums.TicketType + status?: Prisma.EnumTicketStatusFieldUpdateOperationsInput | $Enums.TicketStatus + priority?: Prisma.EnumTicketPriorityFieldUpdateOperationsInput | $Enums.TicketPriority + reason?: Prisma.StringFieldUpdateOperationsInput | string + resolutionNote?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + resolvedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null + report?: Prisma.ReportUpdateOneWithoutTicketsForReportNestedInput + submittedBy?: Prisma.UserUpdateOneRequiredWithoutSubmittedTicketsNestedInput + assignedTo?: Prisma.UserUpdateOneWithoutAssignedTicketsNestedInput + reanalysisScan?: Prisma.ScanUpdateOneWithoutTicketsAsReanalysisNestedInput + reanalysisReport?: Prisma.ReportUpdateOneWithoutTicketsAsReanalysisNestedInput +} + +export type TicketUncheckedUpdateWithoutScanInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + code?: Prisma.StringFieldUpdateOperationsInput | string + type?: Prisma.EnumTicketTypeFieldUpdateOperationsInput | $Enums.TicketType + status?: Prisma.EnumTicketStatusFieldUpdateOperationsInput | $Enums.TicketStatus + priority?: Prisma.EnumTicketPriorityFieldUpdateOperationsInput | $Enums.TicketPriority + reason?: Prisma.StringFieldUpdateOperationsInput | string + reportId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + submittedById?: Prisma.StringFieldUpdateOperationsInput | string + assignedToId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + resolutionNote?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + reanalysisScanId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + reanalysisReportId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + resolvedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null +} + +export type TicketUncheckedUpdateManyWithoutScanInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + code?: Prisma.StringFieldUpdateOperationsInput | string + type?: Prisma.EnumTicketTypeFieldUpdateOperationsInput | $Enums.TicketType + status?: Prisma.EnumTicketStatusFieldUpdateOperationsInput | $Enums.TicketStatus + priority?: Prisma.EnumTicketPriorityFieldUpdateOperationsInput | $Enums.TicketPriority + reason?: Prisma.StringFieldUpdateOperationsInput | string + reportId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + submittedById?: Prisma.StringFieldUpdateOperationsInput | string + assignedToId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + resolutionNote?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + reanalysisScanId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + reanalysisReportId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + resolvedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null +} + +export type TicketUpdateWithoutReanalysisScanInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + code?: Prisma.StringFieldUpdateOperationsInput | string + type?: Prisma.EnumTicketTypeFieldUpdateOperationsInput | $Enums.TicketType + status?: Prisma.EnumTicketStatusFieldUpdateOperationsInput | $Enums.TicketStatus + priority?: Prisma.EnumTicketPriorityFieldUpdateOperationsInput | $Enums.TicketPriority + reason?: Prisma.StringFieldUpdateOperationsInput | string + resolutionNote?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + resolvedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null + scan?: Prisma.ScanUpdateOneWithoutTicketsForScanNestedInput + report?: Prisma.ReportUpdateOneWithoutTicketsForReportNestedInput + submittedBy?: Prisma.UserUpdateOneRequiredWithoutSubmittedTicketsNestedInput + assignedTo?: Prisma.UserUpdateOneWithoutAssignedTicketsNestedInput + reanalysisReport?: Prisma.ReportUpdateOneWithoutTicketsAsReanalysisNestedInput +} + +export type TicketUncheckedUpdateWithoutReanalysisScanInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + code?: Prisma.StringFieldUpdateOperationsInput | string + type?: Prisma.EnumTicketTypeFieldUpdateOperationsInput | $Enums.TicketType + status?: Prisma.EnumTicketStatusFieldUpdateOperationsInput | $Enums.TicketStatus + priority?: Prisma.EnumTicketPriorityFieldUpdateOperationsInput | $Enums.TicketPriority + reason?: Prisma.StringFieldUpdateOperationsInput | string + scanId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + reportId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + submittedById?: Prisma.StringFieldUpdateOperationsInput | string + assignedToId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + resolutionNote?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + reanalysisReportId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + resolvedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null +} + +export type TicketUncheckedUpdateManyWithoutReanalysisScanInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + code?: Prisma.StringFieldUpdateOperationsInput | string + type?: Prisma.EnumTicketTypeFieldUpdateOperationsInput | $Enums.TicketType + status?: Prisma.EnumTicketStatusFieldUpdateOperationsInput | $Enums.TicketStatus + priority?: Prisma.EnumTicketPriorityFieldUpdateOperationsInput | $Enums.TicketPriority + reason?: Prisma.StringFieldUpdateOperationsInput | string + scanId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + reportId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + submittedById?: Prisma.StringFieldUpdateOperationsInput | string + assignedToId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + resolutionNote?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + reanalysisReportId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + resolvedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null +} + +export type TicketCreateManyReportInput = { + id?: string + code: string + type: $Enums.TicketType + status?: $Enums.TicketStatus + priority?: $Enums.TicketPriority + reason: string + scanId?: string | null + submittedById: string + assignedToId?: string | null + resolutionNote?: string | null + reanalysisScanId?: string | null + reanalysisReportId?: string | null + createdAt?: Date | string + updatedAt?: Date | string + resolvedAt?: Date | string | null +} + +export type TicketCreateManyReanalysisReportInput = { + id?: string + code: string + type: $Enums.TicketType + status?: $Enums.TicketStatus + priority?: $Enums.TicketPriority + reason: string + scanId?: string | null + reportId?: string | null + submittedById: string + assignedToId?: string | null + resolutionNote?: string | null + reanalysisScanId?: string | null + createdAt?: Date | string + updatedAt?: Date | string + resolvedAt?: Date | string | null +} + +export type TicketUpdateWithoutReportInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + code?: Prisma.StringFieldUpdateOperationsInput | string + type?: Prisma.EnumTicketTypeFieldUpdateOperationsInput | $Enums.TicketType + status?: Prisma.EnumTicketStatusFieldUpdateOperationsInput | $Enums.TicketStatus + priority?: Prisma.EnumTicketPriorityFieldUpdateOperationsInput | $Enums.TicketPriority + reason?: Prisma.StringFieldUpdateOperationsInput | string + resolutionNote?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + resolvedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null + scan?: Prisma.ScanUpdateOneWithoutTicketsForScanNestedInput + submittedBy?: Prisma.UserUpdateOneRequiredWithoutSubmittedTicketsNestedInput + assignedTo?: Prisma.UserUpdateOneWithoutAssignedTicketsNestedInput + reanalysisScan?: Prisma.ScanUpdateOneWithoutTicketsAsReanalysisNestedInput + reanalysisReport?: Prisma.ReportUpdateOneWithoutTicketsAsReanalysisNestedInput +} + +export type TicketUncheckedUpdateWithoutReportInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + code?: Prisma.StringFieldUpdateOperationsInput | string + type?: Prisma.EnumTicketTypeFieldUpdateOperationsInput | $Enums.TicketType + status?: Prisma.EnumTicketStatusFieldUpdateOperationsInput | $Enums.TicketStatus + priority?: Prisma.EnumTicketPriorityFieldUpdateOperationsInput | $Enums.TicketPriority + reason?: Prisma.StringFieldUpdateOperationsInput | string + scanId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + submittedById?: Prisma.StringFieldUpdateOperationsInput | string + assignedToId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + resolutionNote?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + reanalysisScanId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + reanalysisReportId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + resolvedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null +} + +export type TicketUncheckedUpdateManyWithoutReportInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + code?: Prisma.StringFieldUpdateOperationsInput | string + type?: Prisma.EnumTicketTypeFieldUpdateOperationsInput | $Enums.TicketType + status?: Prisma.EnumTicketStatusFieldUpdateOperationsInput | $Enums.TicketStatus + priority?: Prisma.EnumTicketPriorityFieldUpdateOperationsInput | $Enums.TicketPriority + reason?: Prisma.StringFieldUpdateOperationsInput | string + scanId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + submittedById?: Prisma.StringFieldUpdateOperationsInput | string + assignedToId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + resolutionNote?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + reanalysisScanId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + reanalysisReportId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + resolvedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null +} + +export type TicketUpdateWithoutReanalysisReportInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + code?: Prisma.StringFieldUpdateOperationsInput | string + type?: Prisma.EnumTicketTypeFieldUpdateOperationsInput | $Enums.TicketType + status?: Prisma.EnumTicketStatusFieldUpdateOperationsInput | $Enums.TicketStatus + priority?: Prisma.EnumTicketPriorityFieldUpdateOperationsInput | $Enums.TicketPriority + reason?: Prisma.StringFieldUpdateOperationsInput | string + resolutionNote?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + resolvedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null + scan?: Prisma.ScanUpdateOneWithoutTicketsForScanNestedInput + report?: Prisma.ReportUpdateOneWithoutTicketsForReportNestedInput + submittedBy?: Prisma.UserUpdateOneRequiredWithoutSubmittedTicketsNestedInput + assignedTo?: Prisma.UserUpdateOneWithoutAssignedTicketsNestedInput + reanalysisScan?: Prisma.ScanUpdateOneWithoutTicketsAsReanalysisNestedInput +} + +export type TicketUncheckedUpdateWithoutReanalysisReportInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + code?: Prisma.StringFieldUpdateOperationsInput | string + type?: Prisma.EnumTicketTypeFieldUpdateOperationsInput | $Enums.TicketType + status?: Prisma.EnumTicketStatusFieldUpdateOperationsInput | $Enums.TicketStatus + priority?: Prisma.EnumTicketPriorityFieldUpdateOperationsInput | $Enums.TicketPriority + reason?: Prisma.StringFieldUpdateOperationsInput | string + scanId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + reportId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + submittedById?: Prisma.StringFieldUpdateOperationsInput | string + assignedToId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + resolutionNote?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + reanalysisScanId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + resolvedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null +} + +export type TicketUncheckedUpdateManyWithoutReanalysisReportInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + code?: Prisma.StringFieldUpdateOperationsInput | string + type?: Prisma.EnumTicketTypeFieldUpdateOperationsInput | $Enums.TicketType + status?: Prisma.EnumTicketStatusFieldUpdateOperationsInput | $Enums.TicketStatus + priority?: Prisma.EnumTicketPriorityFieldUpdateOperationsInput | $Enums.TicketPriority + reason?: Prisma.StringFieldUpdateOperationsInput | string + scanId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + reportId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + submittedById?: Prisma.StringFieldUpdateOperationsInput | string + assignedToId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + resolutionNote?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + reanalysisScanId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + resolvedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null +} + + + +export type TicketSelect = runtime.Types.Extensions.GetSelect<{ + id?: boolean + code?: boolean + type?: boolean + status?: boolean + priority?: boolean + reason?: boolean + scanId?: boolean + reportId?: boolean + submittedById?: boolean + assignedToId?: boolean + resolutionNote?: boolean + reanalysisScanId?: boolean + reanalysisReportId?: boolean + createdAt?: boolean + updatedAt?: boolean + resolvedAt?: boolean + scan?: boolean | Prisma.Ticket$scanArgs + report?: boolean | Prisma.Ticket$reportArgs + submittedBy?: boolean | Prisma.UserDefaultArgs + assignedTo?: boolean | Prisma.Ticket$assignedToArgs + reanalysisScan?: boolean | Prisma.Ticket$reanalysisScanArgs + reanalysisReport?: boolean | Prisma.Ticket$reanalysisReportArgs +}, ExtArgs["result"]["ticket"]> + +export type TicketSelectCreateManyAndReturn = runtime.Types.Extensions.GetSelect<{ + id?: boolean + code?: boolean + type?: boolean + status?: boolean + priority?: boolean + reason?: boolean + scanId?: boolean + reportId?: boolean + submittedById?: boolean + assignedToId?: boolean + resolutionNote?: boolean + reanalysisScanId?: boolean + reanalysisReportId?: boolean + createdAt?: boolean + updatedAt?: boolean + resolvedAt?: boolean + scan?: boolean | Prisma.Ticket$scanArgs + report?: boolean | Prisma.Ticket$reportArgs + submittedBy?: boolean | Prisma.UserDefaultArgs + assignedTo?: boolean | Prisma.Ticket$assignedToArgs + reanalysisScan?: boolean | Prisma.Ticket$reanalysisScanArgs + reanalysisReport?: boolean | Prisma.Ticket$reanalysisReportArgs +}, ExtArgs["result"]["ticket"]> + +export type TicketSelectUpdateManyAndReturn = runtime.Types.Extensions.GetSelect<{ + id?: boolean + code?: boolean + type?: boolean + status?: boolean + priority?: boolean + reason?: boolean + scanId?: boolean + reportId?: boolean + submittedById?: boolean + assignedToId?: boolean + resolutionNote?: boolean + reanalysisScanId?: boolean + reanalysisReportId?: boolean + createdAt?: boolean + updatedAt?: boolean + resolvedAt?: boolean + scan?: boolean | Prisma.Ticket$scanArgs + report?: boolean | Prisma.Ticket$reportArgs + submittedBy?: boolean | Prisma.UserDefaultArgs + assignedTo?: boolean | Prisma.Ticket$assignedToArgs + reanalysisScan?: boolean | Prisma.Ticket$reanalysisScanArgs + reanalysisReport?: boolean | Prisma.Ticket$reanalysisReportArgs +}, ExtArgs["result"]["ticket"]> + +export type TicketSelectScalar = { + id?: boolean + code?: boolean + type?: boolean + status?: boolean + priority?: boolean + reason?: boolean + scanId?: boolean + reportId?: boolean + submittedById?: boolean + assignedToId?: boolean + resolutionNote?: boolean + reanalysisScanId?: boolean + reanalysisReportId?: boolean + createdAt?: boolean + updatedAt?: boolean + resolvedAt?: boolean +} + +export type TicketOmit = runtime.Types.Extensions.GetOmit<"id" | "code" | "type" | "status" | "priority" | "reason" | "scanId" | "reportId" | "submittedById" | "assignedToId" | "resolutionNote" | "reanalysisScanId" | "reanalysisReportId" | "createdAt" | "updatedAt" | "resolvedAt", ExtArgs["result"]["ticket"]> +export type TicketInclude = { + scan?: boolean | Prisma.Ticket$scanArgs + report?: boolean | Prisma.Ticket$reportArgs + submittedBy?: boolean | Prisma.UserDefaultArgs + assignedTo?: boolean | Prisma.Ticket$assignedToArgs + reanalysisScan?: boolean | Prisma.Ticket$reanalysisScanArgs + reanalysisReport?: boolean | Prisma.Ticket$reanalysisReportArgs +} +export type TicketIncludeCreateManyAndReturn = { + scan?: boolean | Prisma.Ticket$scanArgs + report?: boolean | Prisma.Ticket$reportArgs + submittedBy?: boolean | Prisma.UserDefaultArgs + assignedTo?: boolean | Prisma.Ticket$assignedToArgs + reanalysisScan?: boolean | Prisma.Ticket$reanalysisScanArgs + reanalysisReport?: boolean | Prisma.Ticket$reanalysisReportArgs +} +export type TicketIncludeUpdateManyAndReturn = { + scan?: boolean | Prisma.Ticket$scanArgs + report?: boolean | Prisma.Ticket$reportArgs + submittedBy?: boolean | Prisma.UserDefaultArgs + assignedTo?: boolean | Prisma.Ticket$assignedToArgs + reanalysisScan?: boolean | Prisma.Ticket$reanalysisScanArgs + reanalysisReport?: boolean | Prisma.Ticket$reanalysisReportArgs +} + +export type $TicketPayload = { + name: "Ticket" + objects: { + scan: Prisma.$ScanPayload | null + report: Prisma.$ReportPayload | null + submittedBy: Prisma.$UserPayload + assignedTo: Prisma.$UserPayload | null + reanalysisScan: Prisma.$ScanPayload | null + reanalysisReport: Prisma.$ReportPayload | null + } + scalars: runtime.Types.Extensions.GetPayloadResult<{ + id: string + code: string + type: $Enums.TicketType + status: $Enums.TicketStatus + priority: $Enums.TicketPriority + reason: string + scanId: string | null + reportId: string | null + submittedById: string + assignedToId: string | null + resolutionNote: string | null + reanalysisScanId: string | null + reanalysisReportId: string | null + createdAt: Date + updatedAt: Date + resolvedAt: Date | null + }, ExtArgs["result"]["ticket"]> + composites: {} +} + +export type TicketGetPayload = runtime.Types.Result.GetResult + +export type TicketCountArgs = + Omit & { + select?: TicketCountAggregateInputType | true + } + +export interface TicketDelegate { + [K: symbol]: { types: Prisma.TypeMap['model']['Ticket'], meta: { name: 'Ticket' } } + /** + * Find zero or one Ticket that matches the filter. + * @param {TicketFindUniqueArgs} args - Arguments to find a Ticket + * @example + * // Get one Ticket + * const ticket = await prisma.ticket.findUnique({ + * where: { + * // ... provide filter here + * } + * }) + */ + findUnique(args: Prisma.SelectSubset>): Prisma.Prisma__TicketClient, T, "findUnique", GlobalOmitOptions> | null, null, ExtArgs, GlobalOmitOptions> + + /** + * Find one Ticket that matches the filter or throw an error with `error.code='P2025'` + * if no matches were found. + * @param {TicketFindUniqueOrThrowArgs} args - Arguments to find a Ticket + * @example + * // Get one Ticket + * const ticket = await prisma.ticket.findUniqueOrThrow({ + * where: { + * // ... provide filter here + * } + * }) + */ + findUniqueOrThrow(args: Prisma.SelectSubset>): Prisma.Prisma__TicketClient, T, "findUniqueOrThrow", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + /** + * Find the first Ticket that matches the filter. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {TicketFindFirstArgs} args - Arguments to find a Ticket + * @example + * // Get one Ticket + * const ticket = await prisma.ticket.findFirst({ + * where: { + * // ... provide filter here + * } + * }) + */ + findFirst(args?: Prisma.SelectSubset>): Prisma.Prisma__TicketClient, T, "findFirst", GlobalOmitOptions> | null, null, ExtArgs, GlobalOmitOptions> + + /** + * Find the first Ticket that matches the filter or + * throw `PrismaKnownClientError` with `P2025` code if no matches were found. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {TicketFindFirstOrThrowArgs} args - Arguments to find a Ticket + * @example + * // Get one Ticket + * const ticket = await prisma.ticket.findFirstOrThrow({ + * where: { + * // ... provide filter here + * } + * }) + */ + findFirstOrThrow(args?: Prisma.SelectSubset>): Prisma.Prisma__TicketClient, T, "findFirstOrThrow", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + /** + * Find zero or more Tickets that matches the filter. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {TicketFindManyArgs} args - Arguments to filter and select certain fields only. + * @example + * // Get all Tickets + * const tickets = await prisma.ticket.findMany() + * + * // Get first 10 Tickets + * const tickets = await prisma.ticket.findMany({ take: 10 }) + * + * // Only select the `id` + * const ticketWithIdOnly = await prisma.ticket.findMany({ select: { id: true } }) + * + */ + findMany(args?: Prisma.SelectSubset>): Prisma.PrismaPromise, T, "findMany", GlobalOmitOptions>> + + /** + * Create a Ticket. + * @param {TicketCreateArgs} args - Arguments to create a Ticket. + * @example + * // Create one Ticket + * const Ticket = await prisma.ticket.create({ + * data: { + * // ... data to create a Ticket + * } + * }) + * + */ + create(args: Prisma.SelectSubset>): Prisma.Prisma__TicketClient, T, "create", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + /** + * Create many Tickets. + * @param {TicketCreateManyArgs} args - Arguments to create many Tickets. + * @example + * // Create many Tickets + * const ticket = await prisma.ticket.createMany({ + * data: [ + * // ... provide data here + * ] + * }) + * + */ + createMany(args?: Prisma.SelectSubset>): Prisma.PrismaPromise + + /** + * Create many Tickets and returns the data saved in the database. + * @param {TicketCreateManyAndReturnArgs} args - Arguments to create many Tickets. + * @example + * // Create many Tickets + * const ticket = await prisma.ticket.createManyAndReturn({ + * data: [ + * // ... provide data here + * ] + * }) + * + * // Create many Tickets and only return the `id` + * const ticketWithIdOnly = await prisma.ticket.createManyAndReturn({ + * select: { id: true }, + * data: [ + * // ... provide data here + * ] + * }) + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * + */ + createManyAndReturn(args?: Prisma.SelectSubset>): Prisma.PrismaPromise, T, "createManyAndReturn", GlobalOmitOptions>> + + /** + * Delete a Ticket. + * @param {TicketDeleteArgs} args - Arguments to delete one Ticket. + * @example + * // Delete one Ticket + * const Ticket = await prisma.ticket.delete({ + * where: { + * // ... filter to delete one Ticket + * } + * }) + * + */ + delete(args: Prisma.SelectSubset>): Prisma.Prisma__TicketClient, T, "delete", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + /** + * Update one Ticket. + * @param {TicketUpdateArgs} args - Arguments to update one Ticket. + * @example + * // Update one Ticket + * const ticket = await prisma.ticket.update({ + * where: { + * // ... provide filter here + * }, + * data: { + * // ... provide data here + * } + * }) + * + */ + update(args: Prisma.SelectSubset>): Prisma.Prisma__TicketClient, T, "update", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + /** + * Delete zero or more Tickets. + * @param {TicketDeleteManyArgs} args - Arguments to filter Tickets to delete. + * @example + * // Delete a few Tickets + * const { count } = await prisma.ticket.deleteMany({ + * where: { + * // ... provide filter here + * } + * }) + * + */ + deleteMany(args?: Prisma.SelectSubset>): Prisma.PrismaPromise + + /** + * Update zero or more Tickets. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {TicketUpdateManyArgs} args - Arguments to update one or more rows. + * @example + * // Update many Tickets + * const ticket = await prisma.ticket.updateMany({ + * where: { + * // ... provide filter here + * }, + * data: { + * // ... provide data here + * } + * }) + * + */ + updateMany(args: Prisma.SelectSubset>): Prisma.PrismaPromise + + /** + * Update zero or more Tickets and returns the data updated in the database. + * @param {TicketUpdateManyAndReturnArgs} args - Arguments to update many Tickets. + * @example + * // Update many Tickets + * const ticket = await prisma.ticket.updateManyAndReturn({ + * where: { + * // ... provide filter here + * }, + * data: [ + * // ... provide data here + * ] + * }) + * + * // Update zero or more Tickets and only return the `id` + * const ticketWithIdOnly = await prisma.ticket.updateManyAndReturn({ + * select: { id: true }, + * where: { + * // ... provide filter here + * }, + * data: [ + * // ... provide data here + * ] + * }) + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * + */ + updateManyAndReturn(args: Prisma.SelectSubset>): Prisma.PrismaPromise, T, "updateManyAndReturn", GlobalOmitOptions>> + + /** + * Create or update one Ticket. + * @param {TicketUpsertArgs} args - Arguments to update or create a Ticket. + * @example + * // Update or create a Ticket + * const ticket = await prisma.ticket.upsert({ + * create: { + * // ... data to create a Ticket + * }, + * update: { + * // ... in case it already exists, update + * }, + * where: { + * // ... the filter for the Ticket we want to update + * } + * }) + */ + upsert(args: Prisma.SelectSubset>): Prisma.Prisma__TicketClient, T, "upsert", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + + /** + * Count the number of Tickets. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {TicketCountArgs} args - Arguments to filter Tickets to count. + * @example + * // Count the number of Tickets + * const count = await prisma.ticket.count({ + * where: { + * // ... the filter for the Tickets we want to count + * } + * }) + **/ + count( + args?: Prisma.Subset, + ): Prisma.PrismaPromise< + T extends runtime.Types.Utils.Record<'select', any> + ? T['select'] extends true + ? number + : Prisma.GetScalarType + : number + > + + /** + * Allows you to perform aggregations operations on a Ticket. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {TicketAggregateArgs} args - Select which aggregations you would like to apply and on what fields. + * @example + * // Ordered by age ascending + * // Where email contains prisma.io + * // Limited to the 10 users + * const aggregations = await prisma.user.aggregate({ + * _avg: { + * age: true, + * }, + * where: { + * email: { + * contains: "prisma.io", + * }, + * }, + * orderBy: { + * age: "asc", + * }, + * take: 10, + * }) + **/ + aggregate(args: Prisma.Subset): Prisma.PrismaPromise> + + /** + * Group by Ticket. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {TicketGroupByArgs} args - Group by arguments. + * @example + * // Group by city, order by createdAt, get count + * const result = await prisma.user.groupBy({ + * by: ['city', 'createdAt'], + * orderBy: { + * createdAt: true + * }, + * _count: { + * _all: true + * }, + * }) + * + **/ + groupBy< + T extends TicketGroupByArgs, + HasSelectOrTake extends Prisma.Or< + Prisma.Extends<'skip', Prisma.Keys>, + Prisma.Extends<'take', Prisma.Keys> + >, + OrderByArg extends Prisma.True extends HasSelectOrTake + ? { orderBy: TicketGroupByArgs['orderBy'] } + : { orderBy?: TicketGroupByArgs['orderBy'] }, + OrderFields extends Prisma.ExcludeUnderscoreKeys>>, + ByFields extends Prisma.MaybeTupleToUnion, + ByValid extends Prisma.Has, + HavingFields extends Prisma.GetHavingFields, + HavingValid extends Prisma.Has, + ByEmpty extends T['by'] extends never[] ? Prisma.True : Prisma.False, + InputErrors extends ByEmpty extends Prisma.True + ? `Error: "by" must not be empty.` + : HavingValid extends Prisma.False + ? { + [P in HavingFields]: P extends ByFields + ? never + : P extends string + ? `Error: Field "${P}" used in "having" needs to be provided in "by".` + : [ + Error, + 'Field ', + P, + ` in "having" needs to be provided in "by"`, + ] + }[HavingFields] + : 'take' extends Prisma.Keys + ? 'orderBy' extends Prisma.Keys + ? ByValid extends Prisma.True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + : 'Error: If you provide "take", you also need to provide "orderBy"' + : 'skip' extends Prisma.Keys + ? 'orderBy' extends Prisma.Keys + ? ByValid extends Prisma.True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + : 'Error: If you provide "skip", you also need to provide "orderBy"' + : ByValid extends Prisma.True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + >(args: Prisma.SubsetIntersection & InputErrors): {} extends InputErrors ? GetTicketGroupByPayload : Prisma.PrismaPromise +/** + * Fields of the Ticket model + */ +readonly fields: TicketFieldRefs; +} + +/** + * The delegate class that acts as a "Promise-like" for Ticket. + * Why is this prefixed with `Prisma__`? + * Because we want to prevent naming conflicts as mentioned in + * https://github.com/prisma/prisma-client-js/issues/707 + */ +export interface Prisma__TicketClient extends Prisma.PrismaPromise { + readonly [Symbol.toStringTag]: "PrismaPromise" + scan = {}>(args?: Prisma.Subset>): Prisma.Prisma__ScanClient, T, "findUniqueOrThrow", GlobalOmitOptions> | null, null, ExtArgs, GlobalOmitOptions> + report = {}>(args?: Prisma.Subset>): Prisma.Prisma__ReportClient, T, "findUniqueOrThrow", GlobalOmitOptions> | null, null, ExtArgs, GlobalOmitOptions> + submittedBy = {}>(args?: Prisma.Subset>): Prisma.Prisma__UserClient, T, "findUniqueOrThrow", GlobalOmitOptions> | Null, Null, ExtArgs, GlobalOmitOptions> + assignedTo = {}>(args?: Prisma.Subset>): Prisma.Prisma__UserClient, T, "findUniqueOrThrow", GlobalOmitOptions> | null, null, ExtArgs, GlobalOmitOptions> + reanalysisScan = {}>(args?: Prisma.Subset>): Prisma.Prisma__ScanClient, T, "findUniqueOrThrow", GlobalOmitOptions> | null, null, ExtArgs, GlobalOmitOptions> + reanalysisReport = {}>(args?: Prisma.Subset>): Prisma.Prisma__ReportClient, T, "findUniqueOrThrow", GlobalOmitOptions> | null, null, ExtArgs, GlobalOmitOptions> + /** + * Attaches callbacks for the resolution and/or rejection of the Promise. + * @param onfulfilled The callback to execute when the Promise is resolved. + * @param onrejected The callback to execute when the Promise is rejected. + * @returns A Promise for the completion of which ever callback is executed. + */ + then(onfulfilled?: ((value: T) => TResult1 | PromiseLike) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike) | undefined | null): runtime.Types.Utils.JsPromise + /** + * Attaches a callback for only the rejection of the Promise. + * @param onrejected The callback to execute when the Promise is rejected. + * @returns A Promise for the completion of the callback. + */ + catch(onrejected?: ((reason: any) => TResult | PromiseLike) | undefined | null): runtime.Types.Utils.JsPromise + /** + * Attaches a callback that is invoked when the Promise is settled (fulfilled or rejected). The + * resolved value cannot be modified from the callback. + * @param onfinally The callback to execute when the Promise is settled (fulfilled or rejected). + * @returns A Promise for the completion of the callback. + */ + finally(onfinally?: (() => void) | undefined | null): runtime.Types.Utils.JsPromise +} + + + + +/** + * Fields of the Ticket model + */ +export interface TicketFieldRefs { + readonly id: Prisma.FieldRef<"Ticket", 'String'> + readonly code: Prisma.FieldRef<"Ticket", 'String'> + readonly type: Prisma.FieldRef<"Ticket", 'TicketType'> + readonly status: Prisma.FieldRef<"Ticket", 'TicketStatus'> + readonly priority: Prisma.FieldRef<"Ticket", 'TicketPriority'> + readonly reason: Prisma.FieldRef<"Ticket", 'String'> + readonly scanId: Prisma.FieldRef<"Ticket", 'String'> + readonly reportId: Prisma.FieldRef<"Ticket", 'String'> + readonly submittedById: Prisma.FieldRef<"Ticket", 'String'> + readonly assignedToId: Prisma.FieldRef<"Ticket", 'String'> + readonly resolutionNote: Prisma.FieldRef<"Ticket", 'String'> + readonly reanalysisScanId: Prisma.FieldRef<"Ticket", 'String'> + readonly reanalysisReportId: Prisma.FieldRef<"Ticket", 'String'> + readonly createdAt: Prisma.FieldRef<"Ticket", 'DateTime'> + readonly updatedAt: Prisma.FieldRef<"Ticket", 'DateTime'> + readonly resolvedAt: Prisma.FieldRef<"Ticket", 'DateTime'> +} + + +// Custom InputTypes +/** + * Ticket findUnique + */ +export type TicketFindUniqueArgs = { + /** + * Select specific fields to fetch from the Ticket + */ + select?: Prisma.TicketSelect | null + /** + * Omit specific fields from the Ticket + */ + omit?: Prisma.TicketOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.TicketInclude | null + /** + * Filter, which Ticket to fetch. + */ + where: Prisma.TicketWhereUniqueInput +} + +/** + * Ticket findUniqueOrThrow + */ +export type TicketFindUniqueOrThrowArgs = { + /** + * Select specific fields to fetch from the Ticket + */ + select?: Prisma.TicketSelect | null + /** + * Omit specific fields from the Ticket + */ + omit?: Prisma.TicketOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.TicketInclude | null + /** + * Filter, which Ticket to fetch. + */ + where: Prisma.TicketWhereUniqueInput +} + +/** + * Ticket findFirst + */ +export type TicketFindFirstArgs = { + /** + * Select specific fields to fetch from the Ticket + */ + select?: Prisma.TicketSelect | null + /** + * Omit specific fields from the Ticket + */ + omit?: Prisma.TicketOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.TicketInclude | null + /** + * Filter, which Ticket to fetch. + */ + where?: Prisma.TicketWhereInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/sorting Sorting Docs} + * + * Determine the order of Tickets to fetch. + */ + orderBy?: Prisma.TicketOrderByWithRelationInput | Prisma.TicketOrderByWithRelationInput[] + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination#cursor-based-pagination Cursor Docs} + * + * Sets the position for searching for Tickets. + */ + cursor?: Prisma.TicketWhereUniqueInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Take `±n` Tickets from the position of the cursor. + */ + take?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Skip the first `n` Tickets. + */ + skip?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/distinct Distinct Docs} + * + * Filter by unique combinations of Tickets. + */ + distinct?: Prisma.TicketScalarFieldEnum | Prisma.TicketScalarFieldEnum[] +} + +/** + * Ticket findFirstOrThrow + */ +export type TicketFindFirstOrThrowArgs = { + /** + * Select specific fields to fetch from the Ticket + */ + select?: Prisma.TicketSelect | null + /** + * Omit specific fields from the Ticket + */ + omit?: Prisma.TicketOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.TicketInclude | null + /** + * Filter, which Ticket to fetch. + */ + where?: Prisma.TicketWhereInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/sorting Sorting Docs} + * + * Determine the order of Tickets to fetch. + */ + orderBy?: Prisma.TicketOrderByWithRelationInput | Prisma.TicketOrderByWithRelationInput[] + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination#cursor-based-pagination Cursor Docs} + * + * Sets the position for searching for Tickets. + */ + cursor?: Prisma.TicketWhereUniqueInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Take `±n` Tickets from the position of the cursor. + */ + take?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Skip the first `n` Tickets. + */ + skip?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/distinct Distinct Docs} + * + * Filter by unique combinations of Tickets. + */ + distinct?: Prisma.TicketScalarFieldEnum | Prisma.TicketScalarFieldEnum[] +} + +/** + * Ticket findMany + */ +export type TicketFindManyArgs = { + /** + * Select specific fields to fetch from the Ticket + */ + select?: Prisma.TicketSelect | null + /** + * Omit specific fields from the Ticket + */ + omit?: Prisma.TicketOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.TicketInclude | null + /** + * Filter, which Tickets to fetch. + */ + where?: Prisma.TicketWhereInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/sorting Sorting Docs} + * + * Determine the order of Tickets to fetch. + */ + orderBy?: Prisma.TicketOrderByWithRelationInput | Prisma.TicketOrderByWithRelationInput[] + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination#cursor-based-pagination Cursor Docs} + * + * Sets the position for listing Tickets. + */ + cursor?: Prisma.TicketWhereUniqueInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Take `±n` Tickets from the position of the cursor. + */ + take?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Skip the first `n` Tickets. + */ + skip?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/distinct Distinct Docs} + * + * Filter by unique combinations of Tickets. + */ + distinct?: Prisma.TicketScalarFieldEnum | Prisma.TicketScalarFieldEnum[] +} + +/** + * Ticket create + */ +export type TicketCreateArgs = { + /** + * Select specific fields to fetch from the Ticket + */ + select?: Prisma.TicketSelect | null + /** + * Omit specific fields from the Ticket + */ + omit?: Prisma.TicketOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.TicketInclude | null + /** + * The data needed to create a Ticket. + */ + data: Prisma.XOR +} + +/** + * Ticket createMany + */ +export type TicketCreateManyArgs = { + /** + * The data used to create many Tickets. + */ + data: Prisma.TicketCreateManyInput | Prisma.TicketCreateManyInput[] + skipDuplicates?: boolean +} + +/** + * Ticket createManyAndReturn + */ +export type TicketCreateManyAndReturnArgs = { + /** + * Select specific fields to fetch from the Ticket + */ + select?: Prisma.TicketSelectCreateManyAndReturn | null + /** + * Omit specific fields from the Ticket + */ + omit?: Prisma.TicketOmit | null + /** + * The data used to create many Tickets. + */ + data: Prisma.TicketCreateManyInput | Prisma.TicketCreateManyInput[] + skipDuplicates?: boolean + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.TicketIncludeCreateManyAndReturn | null +} + +/** + * Ticket update + */ +export type TicketUpdateArgs = { + /** + * Select specific fields to fetch from the Ticket + */ + select?: Prisma.TicketSelect | null + /** + * Omit specific fields from the Ticket + */ + omit?: Prisma.TicketOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.TicketInclude | null + /** + * The data needed to update a Ticket. + */ + data: Prisma.XOR + /** + * Choose, which Ticket to update. + */ + where: Prisma.TicketWhereUniqueInput +} + +/** + * Ticket updateMany + */ +export type TicketUpdateManyArgs = { + /** + * The data used to update Tickets. + */ + data: Prisma.XOR + /** + * Filter which Tickets to update + */ + where?: Prisma.TicketWhereInput + /** + * Limit how many Tickets to update. + */ + limit?: number +} + +/** + * Ticket updateManyAndReturn + */ +export type TicketUpdateManyAndReturnArgs = { + /** + * Select specific fields to fetch from the Ticket + */ + select?: Prisma.TicketSelectUpdateManyAndReturn | null + /** + * Omit specific fields from the Ticket + */ + omit?: Prisma.TicketOmit | null + /** + * The data used to update Tickets. + */ + data: Prisma.XOR + /** + * Filter which Tickets to update + */ + where?: Prisma.TicketWhereInput + /** + * Limit how many Tickets to update. + */ + limit?: number + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.TicketIncludeUpdateManyAndReturn | null +} + +/** + * Ticket upsert + */ +export type TicketUpsertArgs = { + /** + * Select specific fields to fetch from the Ticket + */ + select?: Prisma.TicketSelect | null + /** + * Omit specific fields from the Ticket + */ + omit?: Prisma.TicketOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.TicketInclude | null + /** + * The filter to search for the Ticket to update in case it exists. + */ + where: Prisma.TicketWhereUniqueInput + /** + * In case the Ticket found by the `where` argument doesn't exist, create a new Ticket with this data. + */ + create: Prisma.XOR + /** + * In case the Ticket was found with the provided `where` argument, update it with this data. + */ + update: Prisma.XOR +} + +/** + * Ticket delete + */ +export type TicketDeleteArgs = { + /** + * Select specific fields to fetch from the Ticket + */ + select?: Prisma.TicketSelect | null + /** + * Omit specific fields from the Ticket + */ + omit?: Prisma.TicketOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.TicketInclude | null + /** + * Filter which Ticket to delete. + */ + where: Prisma.TicketWhereUniqueInput +} + +/** + * Ticket deleteMany + */ +export type TicketDeleteManyArgs = { + /** + * Filter which Tickets to delete + */ + where?: Prisma.TicketWhereInput + /** + * Limit how many Tickets to delete. + */ + limit?: number +} + +/** + * Ticket.scan + */ +export type Ticket$scanArgs = { + /** + * Select specific fields to fetch from the Scan + */ + select?: Prisma.ScanSelect | null + /** + * Omit specific fields from the Scan + */ + omit?: Prisma.ScanOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.ScanInclude | null + where?: Prisma.ScanWhereInput +} + +/** + * Ticket.report + */ +export type Ticket$reportArgs = { + /** + * Select specific fields to fetch from the Report + */ + select?: Prisma.ReportSelect | null + /** + * Omit specific fields from the Report + */ + omit?: Prisma.ReportOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.ReportInclude | null + where?: Prisma.ReportWhereInput +} + +/** + * Ticket.assignedTo + */ +export type Ticket$assignedToArgs = { + /** + * Select specific fields to fetch from the User + */ + select?: Prisma.UserSelect | null + /** + * Omit specific fields from the User + */ + omit?: Prisma.UserOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.UserInclude | null + where?: Prisma.UserWhereInput +} + +/** + * Ticket.reanalysisScan + */ +export type Ticket$reanalysisScanArgs = { + /** + * Select specific fields to fetch from the Scan + */ + select?: Prisma.ScanSelect | null + /** + * Omit specific fields from the Scan + */ + omit?: Prisma.ScanOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.ScanInclude | null + where?: Prisma.ScanWhereInput +} + +/** + * Ticket.reanalysisReport + */ +export type Ticket$reanalysisReportArgs = { + /** + * Select specific fields to fetch from the Report + */ + select?: Prisma.ReportSelect | null + /** + * Omit specific fields from the Report + */ + omit?: Prisma.ReportOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.ReportInclude | null + where?: Prisma.ReportWhereInput +} + +/** + * Ticket without action + */ +export type TicketDefaultArgs = { + /** + * Select specific fields to fetch from the Ticket + */ + select?: Prisma.TicketSelect | null + /** + * Omit specific fields from the Ticket + */ + omit?: Prisma.TicketOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.TicketInclude | null +} diff --git a/server/prisma/generated/client/models/User.ts b/server/prisma/generated/client/models/User.ts index 4f9d5dc..a12ffd5 100644 --- a/server/prisma/generated/client/models/User.ts +++ b/server/prisma/generated/client/models/User.ts @@ -327,6 +327,8 @@ export type UserWhereInput = { subscription?: Prisma.XOR | null payments?: Prisma.PaymentListRelationFilter auditLogs?: Prisma.AuditLogListRelationFilter + submittedTickets?: Prisma.TicketListRelationFilter + assignedTickets?: Prisma.TicketListRelationFilter } export type UserOrderByWithRelationInput = { @@ -358,6 +360,8 @@ export type UserOrderByWithRelationInput = { subscription?: Prisma.SubscriptionOrderByWithRelationInput payments?: Prisma.PaymentOrderByRelationAggregateInput auditLogs?: Prisma.AuditLogOrderByRelationAggregateInput + submittedTickets?: Prisma.TicketOrderByRelationAggregateInput + assignedTickets?: Prisma.TicketOrderByRelationAggregateInput } export type UserWhereUniqueInput = Prisma.AtLeast<{ @@ -392,6 +396,8 @@ export type UserWhereUniqueInput = Prisma.AtLeast<{ subscription?: Prisma.XOR | null payments?: Prisma.PaymentListRelationFilter auditLogs?: Prisma.AuditLogListRelationFilter + submittedTickets?: Prisma.TicketListRelationFilter + assignedTickets?: Prisma.TicketListRelationFilter }, "id" | "username" | "email" | "googleId"> export type UserOrderByWithAggregationInput = { @@ -471,6 +477,8 @@ export type UserCreateInput = { subscription?: Prisma.SubscriptionCreateNestedOneWithoutUserInput payments?: Prisma.PaymentCreateNestedManyWithoutUserInput auditLogs?: Prisma.AuditLogCreateNestedManyWithoutActorInput + submittedTickets?: Prisma.TicketCreateNestedManyWithoutSubmittedByInput + assignedTickets?: Prisma.TicketCreateNestedManyWithoutAssignedToInput } export type UserUncheckedCreateInput = { @@ -502,6 +510,8 @@ export type UserUncheckedCreateInput = { subscription?: Prisma.SubscriptionUncheckedCreateNestedOneWithoutUserInput payments?: Prisma.PaymentUncheckedCreateNestedManyWithoutUserInput auditLogs?: Prisma.AuditLogUncheckedCreateNestedManyWithoutActorInput + submittedTickets?: Prisma.TicketUncheckedCreateNestedManyWithoutSubmittedByInput + assignedTickets?: Prisma.TicketUncheckedCreateNestedManyWithoutAssignedToInput } export type UserUpdateInput = { @@ -533,6 +543,8 @@ export type UserUpdateInput = { subscription?: Prisma.SubscriptionUpdateOneWithoutUserNestedInput payments?: Prisma.PaymentUpdateManyWithoutUserNestedInput auditLogs?: Prisma.AuditLogUpdateManyWithoutActorNestedInput + submittedTickets?: Prisma.TicketUpdateManyWithoutSubmittedByNestedInput + assignedTickets?: Prisma.TicketUpdateManyWithoutAssignedToNestedInput } export type UserUncheckedUpdateInput = { @@ -564,6 +576,8 @@ export type UserUncheckedUpdateInput = { subscription?: Prisma.SubscriptionUncheckedUpdateOneWithoutUserNestedInput payments?: Prisma.PaymentUncheckedUpdateManyWithoutUserNestedInput auditLogs?: Prisma.AuditLogUncheckedUpdateManyWithoutActorNestedInput + submittedTickets?: Prisma.TicketUncheckedUpdateManyWithoutSubmittedByNestedInput + assignedTickets?: Prisma.TicketUncheckedUpdateManyWithoutAssignedToNestedInput } export type UserCreateManyInput = { @@ -884,6 +898,36 @@ export type UserUpdateOneRequiredWithoutPaymentsNestedInput = { update?: Prisma.XOR, Prisma.UserUncheckedUpdateWithoutPaymentsInput> } +export type UserCreateNestedOneWithoutSubmittedTicketsInput = { + create?: Prisma.XOR + connectOrCreate?: Prisma.UserCreateOrConnectWithoutSubmittedTicketsInput + connect?: Prisma.UserWhereUniqueInput +} + +export type UserCreateNestedOneWithoutAssignedTicketsInput = { + create?: Prisma.XOR + connectOrCreate?: Prisma.UserCreateOrConnectWithoutAssignedTicketsInput + connect?: Prisma.UserWhereUniqueInput +} + +export type UserUpdateOneRequiredWithoutSubmittedTicketsNestedInput = { + create?: Prisma.XOR + connectOrCreate?: Prisma.UserCreateOrConnectWithoutSubmittedTicketsInput + upsert?: Prisma.UserUpsertWithoutSubmittedTicketsInput + connect?: Prisma.UserWhereUniqueInput + update?: Prisma.XOR, Prisma.UserUncheckedUpdateWithoutSubmittedTicketsInput> +} + +export type UserUpdateOneWithoutAssignedTicketsNestedInput = { + create?: Prisma.XOR + connectOrCreate?: Prisma.UserCreateOrConnectWithoutAssignedTicketsInput + upsert?: Prisma.UserUpsertWithoutAssignedTicketsInput + disconnect?: Prisma.UserWhereInput | boolean + delete?: Prisma.UserWhereInput | boolean + connect?: Prisma.UserWhereUniqueInput + update?: Prisma.XOR, Prisma.UserUncheckedUpdateWithoutAssignedTicketsInput> +} + export type UserCreateNestedOneWithoutAuditLogsInput = { create?: Prisma.XOR connectOrCreate?: Prisma.UserCreateOrConnectWithoutAuditLogsInput @@ -928,6 +972,8 @@ export type UserCreateWithoutOwnedOrgInput = { subscription?: Prisma.SubscriptionCreateNestedOneWithoutUserInput payments?: Prisma.PaymentCreateNestedManyWithoutUserInput auditLogs?: Prisma.AuditLogCreateNestedManyWithoutActorInput + submittedTickets?: Prisma.TicketCreateNestedManyWithoutSubmittedByInput + assignedTickets?: Prisma.TicketCreateNestedManyWithoutAssignedToInput } export type UserUncheckedCreateWithoutOwnedOrgInput = { @@ -958,6 +1004,8 @@ export type UserUncheckedCreateWithoutOwnedOrgInput = { subscription?: Prisma.SubscriptionUncheckedCreateNestedOneWithoutUserInput payments?: Prisma.PaymentUncheckedCreateNestedManyWithoutUserInput auditLogs?: Prisma.AuditLogUncheckedCreateNestedManyWithoutActorInput + submittedTickets?: Prisma.TicketUncheckedCreateNestedManyWithoutSubmittedByInput + assignedTickets?: Prisma.TicketUncheckedCreateNestedManyWithoutAssignedToInput } export type UserCreateOrConnectWithoutOwnedOrgInput = { @@ -1004,6 +1052,8 @@ export type UserUpdateWithoutOwnedOrgInput = { subscription?: Prisma.SubscriptionUpdateOneWithoutUserNestedInput payments?: Prisma.PaymentUpdateManyWithoutUserNestedInput auditLogs?: Prisma.AuditLogUpdateManyWithoutActorNestedInput + submittedTickets?: Prisma.TicketUpdateManyWithoutSubmittedByNestedInput + assignedTickets?: Prisma.TicketUpdateManyWithoutAssignedToNestedInput } export type UserUncheckedUpdateWithoutOwnedOrgInput = { @@ -1034,6 +1084,8 @@ export type UserUncheckedUpdateWithoutOwnedOrgInput = { subscription?: Prisma.SubscriptionUncheckedUpdateOneWithoutUserNestedInput payments?: Prisma.PaymentUncheckedUpdateManyWithoutUserNestedInput auditLogs?: Prisma.AuditLogUncheckedUpdateManyWithoutActorNestedInput + submittedTickets?: Prisma.TicketUncheckedUpdateManyWithoutSubmittedByNestedInput + assignedTickets?: Prisma.TicketUncheckedUpdateManyWithoutAssignedToNestedInput } export type UserCreateWithoutOrgMemberInput = { @@ -1064,6 +1116,8 @@ export type UserCreateWithoutOrgMemberInput = { subscription?: Prisma.SubscriptionCreateNestedOneWithoutUserInput payments?: Prisma.PaymentCreateNestedManyWithoutUserInput auditLogs?: Prisma.AuditLogCreateNestedManyWithoutActorInput + submittedTickets?: Prisma.TicketCreateNestedManyWithoutSubmittedByInput + assignedTickets?: Prisma.TicketCreateNestedManyWithoutAssignedToInput } export type UserUncheckedCreateWithoutOrgMemberInput = { @@ -1094,6 +1148,8 @@ export type UserUncheckedCreateWithoutOrgMemberInput = { subscription?: Prisma.SubscriptionUncheckedCreateNestedOneWithoutUserInput payments?: Prisma.PaymentUncheckedCreateNestedManyWithoutUserInput auditLogs?: Prisma.AuditLogUncheckedCreateNestedManyWithoutActorInput + submittedTickets?: Prisma.TicketUncheckedCreateNestedManyWithoutSubmittedByInput + assignedTickets?: Prisma.TicketUncheckedCreateNestedManyWithoutAssignedToInput } export type UserCreateOrConnectWithoutOrgMemberInput = { @@ -1140,6 +1196,8 @@ export type UserUpdateWithoutOrgMemberInput = { subscription?: Prisma.SubscriptionUpdateOneWithoutUserNestedInput payments?: Prisma.PaymentUpdateManyWithoutUserNestedInput auditLogs?: Prisma.AuditLogUpdateManyWithoutActorNestedInput + submittedTickets?: Prisma.TicketUpdateManyWithoutSubmittedByNestedInput + assignedTickets?: Prisma.TicketUpdateManyWithoutAssignedToNestedInput } export type UserUncheckedUpdateWithoutOrgMemberInput = { @@ -1170,6 +1228,8 @@ export type UserUncheckedUpdateWithoutOrgMemberInput = { subscription?: Prisma.SubscriptionUncheckedUpdateOneWithoutUserNestedInput payments?: Prisma.PaymentUncheckedUpdateManyWithoutUserNestedInput auditLogs?: Prisma.AuditLogUncheckedUpdateManyWithoutActorNestedInput + submittedTickets?: Prisma.TicketUncheckedUpdateManyWithoutSubmittedByNestedInput + assignedTickets?: Prisma.TicketUncheckedUpdateManyWithoutAssignedToNestedInput } export type UserCreateWithoutPatientsInput = { @@ -1200,6 +1260,8 @@ export type UserCreateWithoutPatientsInput = { subscription?: Prisma.SubscriptionCreateNestedOneWithoutUserInput payments?: Prisma.PaymentCreateNestedManyWithoutUserInput auditLogs?: Prisma.AuditLogCreateNestedManyWithoutActorInput + submittedTickets?: Prisma.TicketCreateNestedManyWithoutSubmittedByInput + assignedTickets?: Prisma.TicketCreateNestedManyWithoutAssignedToInput } export type UserUncheckedCreateWithoutPatientsInput = { @@ -1230,6 +1292,8 @@ export type UserUncheckedCreateWithoutPatientsInput = { subscription?: Prisma.SubscriptionUncheckedCreateNestedOneWithoutUserInput payments?: Prisma.PaymentUncheckedCreateNestedManyWithoutUserInput auditLogs?: Prisma.AuditLogUncheckedCreateNestedManyWithoutActorInput + submittedTickets?: Prisma.TicketUncheckedCreateNestedManyWithoutSubmittedByInput + assignedTickets?: Prisma.TicketUncheckedCreateNestedManyWithoutAssignedToInput } export type UserCreateOrConnectWithoutPatientsInput = { @@ -1276,6 +1340,8 @@ export type UserUpdateWithoutPatientsInput = { subscription?: Prisma.SubscriptionUpdateOneWithoutUserNestedInput payments?: Prisma.PaymentUpdateManyWithoutUserNestedInput auditLogs?: Prisma.AuditLogUpdateManyWithoutActorNestedInput + submittedTickets?: Prisma.TicketUpdateManyWithoutSubmittedByNestedInput + assignedTickets?: Prisma.TicketUpdateManyWithoutAssignedToNestedInput } export type UserUncheckedUpdateWithoutPatientsInput = { @@ -1306,6 +1372,8 @@ export type UserUncheckedUpdateWithoutPatientsInput = { subscription?: Prisma.SubscriptionUncheckedUpdateOneWithoutUserNestedInput payments?: Prisma.PaymentUncheckedUpdateManyWithoutUserNestedInput auditLogs?: Prisma.AuditLogUncheckedUpdateManyWithoutActorNestedInput + submittedTickets?: Prisma.TicketUncheckedUpdateManyWithoutSubmittedByNestedInput + assignedTickets?: Prisma.TicketUncheckedUpdateManyWithoutAssignedToNestedInput } export type UserCreateWithoutScansInput = { @@ -1336,6 +1404,8 @@ export type UserCreateWithoutScansInput = { subscription?: Prisma.SubscriptionCreateNestedOneWithoutUserInput payments?: Prisma.PaymentCreateNestedManyWithoutUserInput auditLogs?: Prisma.AuditLogCreateNestedManyWithoutActorInput + submittedTickets?: Prisma.TicketCreateNestedManyWithoutSubmittedByInput + assignedTickets?: Prisma.TicketCreateNestedManyWithoutAssignedToInput } export type UserUncheckedCreateWithoutScansInput = { @@ -1366,6 +1436,8 @@ export type UserUncheckedCreateWithoutScansInput = { subscription?: Prisma.SubscriptionUncheckedCreateNestedOneWithoutUserInput payments?: Prisma.PaymentUncheckedCreateNestedManyWithoutUserInput auditLogs?: Prisma.AuditLogUncheckedCreateNestedManyWithoutActorInput + submittedTickets?: Prisma.TicketUncheckedCreateNestedManyWithoutSubmittedByInput + assignedTickets?: Prisma.TicketUncheckedCreateNestedManyWithoutAssignedToInput } export type UserCreateOrConnectWithoutScansInput = { @@ -1412,6 +1484,8 @@ export type UserUpdateWithoutScansInput = { subscription?: Prisma.SubscriptionUpdateOneWithoutUserNestedInput payments?: Prisma.PaymentUpdateManyWithoutUserNestedInput auditLogs?: Prisma.AuditLogUpdateManyWithoutActorNestedInput + submittedTickets?: Prisma.TicketUpdateManyWithoutSubmittedByNestedInput + assignedTickets?: Prisma.TicketUpdateManyWithoutAssignedToNestedInput } export type UserUncheckedUpdateWithoutScansInput = { @@ -1442,6 +1516,8 @@ export type UserUncheckedUpdateWithoutScansInput = { subscription?: Prisma.SubscriptionUncheckedUpdateOneWithoutUserNestedInput payments?: Prisma.PaymentUncheckedUpdateManyWithoutUserNestedInput auditLogs?: Prisma.AuditLogUncheckedUpdateManyWithoutActorNestedInput + submittedTickets?: Prisma.TicketUncheckedUpdateManyWithoutSubmittedByNestedInput + assignedTickets?: Prisma.TicketUncheckedUpdateManyWithoutAssignedToNestedInput } export type UserCreateWithoutNotificationsInput = { @@ -1472,6 +1548,8 @@ export type UserCreateWithoutNotificationsInput = { subscription?: Prisma.SubscriptionCreateNestedOneWithoutUserInput payments?: Prisma.PaymentCreateNestedManyWithoutUserInput auditLogs?: Prisma.AuditLogCreateNestedManyWithoutActorInput + submittedTickets?: Prisma.TicketCreateNestedManyWithoutSubmittedByInput + assignedTickets?: Prisma.TicketCreateNestedManyWithoutAssignedToInput } export type UserUncheckedCreateWithoutNotificationsInput = { @@ -1502,6 +1580,8 @@ export type UserUncheckedCreateWithoutNotificationsInput = { subscription?: Prisma.SubscriptionUncheckedCreateNestedOneWithoutUserInput payments?: Prisma.PaymentUncheckedCreateNestedManyWithoutUserInput auditLogs?: Prisma.AuditLogUncheckedCreateNestedManyWithoutActorInput + submittedTickets?: Prisma.TicketUncheckedCreateNestedManyWithoutSubmittedByInput + assignedTickets?: Prisma.TicketUncheckedCreateNestedManyWithoutAssignedToInput } export type UserCreateOrConnectWithoutNotificationsInput = { @@ -1548,6 +1628,8 @@ export type UserUpdateWithoutNotificationsInput = { subscription?: Prisma.SubscriptionUpdateOneWithoutUserNestedInput payments?: Prisma.PaymentUpdateManyWithoutUserNestedInput auditLogs?: Prisma.AuditLogUpdateManyWithoutActorNestedInput + submittedTickets?: Prisma.TicketUpdateManyWithoutSubmittedByNestedInput + assignedTickets?: Prisma.TicketUpdateManyWithoutAssignedToNestedInput } export type UserUncheckedUpdateWithoutNotificationsInput = { @@ -1578,6 +1660,8 @@ export type UserUncheckedUpdateWithoutNotificationsInput = { subscription?: Prisma.SubscriptionUncheckedUpdateOneWithoutUserNestedInput payments?: Prisma.PaymentUncheckedUpdateManyWithoutUserNestedInput auditLogs?: Prisma.AuditLogUncheckedUpdateManyWithoutActorNestedInput + submittedTickets?: Prisma.TicketUncheckedUpdateManyWithoutSubmittedByNestedInput + assignedTickets?: Prisma.TicketUncheckedUpdateManyWithoutAssignedToNestedInput } export type UserCreateWithoutEmailNotificationInput = { @@ -1608,6 +1692,8 @@ export type UserCreateWithoutEmailNotificationInput = { subscription?: Prisma.SubscriptionCreateNestedOneWithoutUserInput payments?: Prisma.PaymentCreateNestedManyWithoutUserInput auditLogs?: Prisma.AuditLogCreateNestedManyWithoutActorInput + submittedTickets?: Prisma.TicketCreateNestedManyWithoutSubmittedByInput + assignedTickets?: Prisma.TicketCreateNestedManyWithoutAssignedToInput } export type UserUncheckedCreateWithoutEmailNotificationInput = { @@ -1638,6 +1724,8 @@ export type UserUncheckedCreateWithoutEmailNotificationInput = { subscription?: Prisma.SubscriptionUncheckedCreateNestedOneWithoutUserInput payments?: Prisma.PaymentUncheckedCreateNestedManyWithoutUserInput auditLogs?: Prisma.AuditLogUncheckedCreateNestedManyWithoutActorInput + submittedTickets?: Prisma.TicketUncheckedCreateNestedManyWithoutSubmittedByInput + assignedTickets?: Prisma.TicketUncheckedCreateNestedManyWithoutAssignedToInput } export type UserCreateOrConnectWithoutEmailNotificationInput = { @@ -1684,6 +1772,8 @@ export type UserUpdateWithoutEmailNotificationInput = { subscription?: Prisma.SubscriptionUpdateOneWithoutUserNestedInput payments?: Prisma.PaymentUpdateManyWithoutUserNestedInput auditLogs?: Prisma.AuditLogUpdateManyWithoutActorNestedInput + submittedTickets?: Prisma.TicketUpdateManyWithoutSubmittedByNestedInput + assignedTickets?: Prisma.TicketUpdateManyWithoutAssignedToNestedInput } export type UserUncheckedUpdateWithoutEmailNotificationInput = { @@ -1714,6 +1804,8 @@ export type UserUncheckedUpdateWithoutEmailNotificationInput = { subscription?: Prisma.SubscriptionUncheckedUpdateOneWithoutUserNestedInput payments?: Prisma.PaymentUncheckedUpdateManyWithoutUserNestedInput auditLogs?: Prisma.AuditLogUncheckedUpdateManyWithoutActorNestedInput + submittedTickets?: Prisma.TicketUncheckedUpdateManyWithoutSubmittedByNestedInput + assignedTickets?: Prisma.TicketUncheckedUpdateManyWithoutAssignedToNestedInput } export type UserCreateWithoutInAppNotificationInput = { @@ -1744,6 +1836,8 @@ export type UserCreateWithoutInAppNotificationInput = { subscription?: Prisma.SubscriptionCreateNestedOneWithoutUserInput payments?: Prisma.PaymentCreateNestedManyWithoutUserInput auditLogs?: Prisma.AuditLogCreateNestedManyWithoutActorInput + submittedTickets?: Prisma.TicketCreateNestedManyWithoutSubmittedByInput + assignedTickets?: Prisma.TicketCreateNestedManyWithoutAssignedToInput } export type UserUncheckedCreateWithoutInAppNotificationInput = { @@ -1774,6 +1868,8 @@ export type UserUncheckedCreateWithoutInAppNotificationInput = { subscription?: Prisma.SubscriptionUncheckedCreateNestedOneWithoutUserInput payments?: Prisma.PaymentUncheckedCreateNestedManyWithoutUserInput auditLogs?: Prisma.AuditLogUncheckedCreateNestedManyWithoutActorInput + submittedTickets?: Prisma.TicketUncheckedCreateNestedManyWithoutSubmittedByInput + assignedTickets?: Prisma.TicketUncheckedCreateNestedManyWithoutAssignedToInput } export type UserCreateOrConnectWithoutInAppNotificationInput = { @@ -1820,6 +1916,8 @@ export type UserUpdateWithoutInAppNotificationInput = { subscription?: Prisma.SubscriptionUpdateOneWithoutUserNestedInput payments?: Prisma.PaymentUpdateManyWithoutUserNestedInput auditLogs?: Prisma.AuditLogUpdateManyWithoutActorNestedInput + submittedTickets?: Prisma.TicketUpdateManyWithoutSubmittedByNestedInput + assignedTickets?: Prisma.TicketUpdateManyWithoutAssignedToNestedInput } export type UserUncheckedUpdateWithoutInAppNotificationInput = { @@ -1850,6 +1948,8 @@ export type UserUncheckedUpdateWithoutInAppNotificationInput = { subscription?: Prisma.SubscriptionUncheckedUpdateOneWithoutUserNestedInput payments?: Prisma.PaymentUncheckedUpdateManyWithoutUserNestedInput auditLogs?: Prisma.AuditLogUncheckedUpdateManyWithoutActorNestedInput + submittedTickets?: Prisma.TicketUncheckedUpdateManyWithoutSubmittedByNestedInput + assignedTickets?: Prisma.TicketUncheckedUpdateManyWithoutAssignedToNestedInput } export type UserCreateWithoutSessionsInput = { @@ -1880,6 +1980,8 @@ export type UserCreateWithoutSessionsInput = { subscription?: Prisma.SubscriptionCreateNestedOneWithoutUserInput payments?: Prisma.PaymentCreateNestedManyWithoutUserInput auditLogs?: Prisma.AuditLogCreateNestedManyWithoutActorInput + submittedTickets?: Prisma.TicketCreateNestedManyWithoutSubmittedByInput + assignedTickets?: Prisma.TicketCreateNestedManyWithoutAssignedToInput } export type UserUncheckedCreateWithoutSessionsInput = { @@ -1910,6 +2012,8 @@ export type UserUncheckedCreateWithoutSessionsInput = { subscription?: Prisma.SubscriptionUncheckedCreateNestedOneWithoutUserInput payments?: Prisma.PaymentUncheckedCreateNestedManyWithoutUserInput auditLogs?: Prisma.AuditLogUncheckedCreateNestedManyWithoutActorInput + submittedTickets?: Prisma.TicketUncheckedCreateNestedManyWithoutSubmittedByInput + assignedTickets?: Prisma.TicketUncheckedCreateNestedManyWithoutAssignedToInput } export type UserCreateOrConnectWithoutSessionsInput = { @@ -1956,6 +2060,8 @@ export type UserUpdateWithoutSessionsInput = { subscription?: Prisma.SubscriptionUpdateOneWithoutUserNestedInput payments?: Prisma.PaymentUpdateManyWithoutUserNestedInput auditLogs?: Prisma.AuditLogUpdateManyWithoutActorNestedInput + submittedTickets?: Prisma.TicketUpdateManyWithoutSubmittedByNestedInput + assignedTickets?: Prisma.TicketUpdateManyWithoutAssignedToNestedInput } export type UserUncheckedUpdateWithoutSessionsInput = { @@ -1986,6 +2092,8 @@ export type UserUncheckedUpdateWithoutSessionsInput = { subscription?: Prisma.SubscriptionUncheckedUpdateOneWithoutUserNestedInput payments?: Prisma.PaymentUncheckedUpdateManyWithoutUserNestedInput auditLogs?: Prisma.AuditLogUncheckedUpdateManyWithoutActorNestedInput + submittedTickets?: Prisma.TicketUncheckedUpdateManyWithoutSubmittedByNestedInput + assignedTickets?: Prisma.TicketUncheckedUpdateManyWithoutAssignedToNestedInput } export type UserCreateWithoutSubscriptionInput = { @@ -2016,6 +2124,8 @@ export type UserCreateWithoutSubscriptionInput = { orgMember?: Prisma.OrgMemberCreateNestedOneWithoutUserInput payments?: Prisma.PaymentCreateNestedManyWithoutUserInput auditLogs?: Prisma.AuditLogCreateNestedManyWithoutActorInput + submittedTickets?: Prisma.TicketCreateNestedManyWithoutSubmittedByInput + assignedTickets?: Prisma.TicketCreateNestedManyWithoutAssignedToInput } export type UserUncheckedCreateWithoutSubscriptionInput = { @@ -2046,6 +2156,8 @@ export type UserUncheckedCreateWithoutSubscriptionInput = { orgMember?: Prisma.OrgMemberUncheckedCreateNestedOneWithoutUserInput payments?: Prisma.PaymentUncheckedCreateNestedManyWithoutUserInput auditLogs?: Prisma.AuditLogUncheckedCreateNestedManyWithoutActorInput + submittedTickets?: Prisma.TicketUncheckedCreateNestedManyWithoutSubmittedByInput + assignedTickets?: Prisma.TicketUncheckedCreateNestedManyWithoutAssignedToInput } export type UserCreateOrConnectWithoutSubscriptionInput = { @@ -2092,6 +2204,8 @@ export type UserUpdateWithoutSubscriptionInput = { orgMember?: Prisma.OrgMemberUpdateOneWithoutUserNestedInput payments?: Prisma.PaymentUpdateManyWithoutUserNestedInput auditLogs?: Prisma.AuditLogUpdateManyWithoutActorNestedInput + submittedTickets?: Prisma.TicketUpdateManyWithoutSubmittedByNestedInput + assignedTickets?: Prisma.TicketUpdateManyWithoutAssignedToNestedInput } export type UserUncheckedUpdateWithoutSubscriptionInput = { @@ -2122,6 +2236,8 @@ export type UserUncheckedUpdateWithoutSubscriptionInput = { orgMember?: Prisma.OrgMemberUncheckedUpdateOneWithoutUserNestedInput payments?: Prisma.PaymentUncheckedUpdateManyWithoutUserNestedInput auditLogs?: Prisma.AuditLogUncheckedUpdateManyWithoutActorNestedInput + submittedTickets?: Prisma.TicketUncheckedUpdateManyWithoutSubmittedByNestedInput + assignedTickets?: Prisma.TicketUncheckedUpdateManyWithoutAssignedToNestedInput } export type UserCreateWithoutPaymentsInput = { @@ -2152,6 +2268,8 @@ export type UserCreateWithoutPaymentsInput = { orgMember?: Prisma.OrgMemberCreateNestedOneWithoutUserInput subscription?: Prisma.SubscriptionCreateNestedOneWithoutUserInput auditLogs?: Prisma.AuditLogCreateNestedManyWithoutActorInput + submittedTickets?: Prisma.TicketCreateNestedManyWithoutSubmittedByInput + assignedTickets?: Prisma.TicketCreateNestedManyWithoutAssignedToInput } export type UserUncheckedCreateWithoutPaymentsInput = { @@ -2182,6 +2300,8 @@ export type UserUncheckedCreateWithoutPaymentsInput = { orgMember?: Prisma.OrgMemberUncheckedCreateNestedOneWithoutUserInput subscription?: Prisma.SubscriptionUncheckedCreateNestedOneWithoutUserInput auditLogs?: Prisma.AuditLogUncheckedCreateNestedManyWithoutActorInput + submittedTickets?: Prisma.TicketUncheckedCreateNestedManyWithoutSubmittedByInput + assignedTickets?: Prisma.TicketUncheckedCreateNestedManyWithoutAssignedToInput } export type UserCreateOrConnectWithoutPaymentsInput = { @@ -2228,6 +2348,8 @@ export type UserUpdateWithoutPaymentsInput = { orgMember?: Prisma.OrgMemberUpdateOneWithoutUserNestedInput subscription?: Prisma.SubscriptionUpdateOneWithoutUserNestedInput auditLogs?: Prisma.AuditLogUpdateManyWithoutActorNestedInput + submittedTickets?: Prisma.TicketUpdateManyWithoutSubmittedByNestedInput + assignedTickets?: Prisma.TicketUpdateManyWithoutAssignedToNestedInput } export type UserUncheckedUpdateWithoutPaymentsInput = { @@ -2258,6 +2380,296 @@ export type UserUncheckedUpdateWithoutPaymentsInput = { orgMember?: Prisma.OrgMemberUncheckedUpdateOneWithoutUserNestedInput subscription?: Prisma.SubscriptionUncheckedUpdateOneWithoutUserNestedInput auditLogs?: Prisma.AuditLogUncheckedUpdateManyWithoutActorNestedInput + submittedTickets?: Prisma.TicketUncheckedUpdateManyWithoutSubmittedByNestedInput + assignedTickets?: Prisma.TicketUncheckedUpdateManyWithoutAssignedToNestedInput +} + +export type UserCreateWithoutSubmittedTicketsInput = { + id?: string + username: string + email: string + password?: string | null + googleId?: string | null + profile_image_url?: string | null + plan?: $Enums.Plan + role?: $Enums.Role + is_active?: boolean + total_scans?: number + total_reports?: number + twoFactorSecret?: string | null + twoFactorEnabled?: boolean + reset_password_token?: string | null + reset_token_expires?: Date | string | null + createdAt?: Date | string + updatedAt?: Date | string + patients?: Prisma.PatientCreateNestedManyWithoutCreated_byInput + scans?: Prisma.ScanCreateNestedManyWithoutUploaded_byInput + notifications?: Prisma.NotificationsCreateNestedManyWithoutUserInput + emailNotification?: Prisma.EmailNotificationCreateNestedOneWithoutUserInput + inAppNotification?: Prisma.InAppNotificationCreateNestedOneWithoutUserInput + sessions?: Prisma.SessionCreateNestedManyWithoutUserInput + ownedOrg?: Prisma.OrganizationCreateNestedOneWithoutOwnerInput + orgMember?: Prisma.OrgMemberCreateNestedOneWithoutUserInput + subscription?: Prisma.SubscriptionCreateNestedOneWithoutUserInput + payments?: Prisma.PaymentCreateNestedManyWithoutUserInput + auditLogs?: Prisma.AuditLogCreateNestedManyWithoutActorInput + assignedTickets?: Prisma.TicketCreateNestedManyWithoutAssignedToInput +} + +export type UserUncheckedCreateWithoutSubmittedTicketsInput = { + id?: string + username: string + email: string + password?: string | null + googleId?: string | null + profile_image_url?: string | null + plan?: $Enums.Plan + role?: $Enums.Role + is_active?: boolean + total_scans?: number + total_reports?: number + twoFactorSecret?: string | null + twoFactorEnabled?: boolean + reset_password_token?: string | null + reset_token_expires?: Date | string | null + createdAt?: Date | string + updatedAt?: Date | string + patients?: Prisma.PatientUncheckedCreateNestedManyWithoutCreated_byInput + scans?: Prisma.ScanUncheckedCreateNestedManyWithoutUploaded_byInput + notifications?: Prisma.NotificationsUncheckedCreateNestedManyWithoutUserInput + emailNotification?: Prisma.EmailNotificationUncheckedCreateNestedOneWithoutUserInput + inAppNotification?: Prisma.InAppNotificationUncheckedCreateNestedOneWithoutUserInput + sessions?: Prisma.SessionUncheckedCreateNestedManyWithoutUserInput + ownedOrg?: Prisma.OrganizationUncheckedCreateNestedOneWithoutOwnerInput + orgMember?: Prisma.OrgMemberUncheckedCreateNestedOneWithoutUserInput + subscription?: Prisma.SubscriptionUncheckedCreateNestedOneWithoutUserInput + payments?: Prisma.PaymentUncheckedCreateNestedManyWithoutUserInput + auditLogs?: Prisma.AuditLogUncheckedCreateNestedManyWithoutActorInput + assignedTickets?: Prisma.TicketUncheckedCreateNestedManyWithoutAssignedToInput +} + +export type UserCreateOrConnectWithoutSubmittedTicketsInput = { + where: Prisma.UserWhereUniqueInput + create: Prisma.XOR +} + +export type UserCreateWithoutAssignedTicketsInput = { + id?: string + username: string + email: string + password?: string | null + googleId?: string | null + profile_image_url?: string | null + plan?: $Enums.Plan + role?: $Enums.Role + is_active?: boolean + total_scans?: number + total_reports?: number + twoFactorSecret?: string | null + twoFactorEnabled?: boolean + reset_password_token?: string | null + reset_token_expires?: Date | string | null + createdAt?: Date | string + updatedAt?: Date | string + patients?: Prisma.PatientCreateNestedManyWithoutCreated_byInput + scans?: Prisma.ScanCreateNestedManyWithoutUploaded_byInput + notifications?: Prisma.NotificationsCreateNestedManyWithoutUserInput + emailNotification?: Prisma.EmailNotificationCreateNestedOneWithoutUserInput + inAppNotification?: Prisma.InAppNotificationCreateNestedOneWithoutUserInput + sessions?: Prisma.SessionCreateNestedManyWithoutUserInput + ownedOrg?: Prisma.OrganizationCreateNestedOneWithoutOwnerInput + orgMember?: Prisma.OrgMemberCreateNestedOneWithoutUserInput + subscription?: Prisma.SubscriptionCreateNestedOneWithoutUserInput + payments?: Prisma.PaymentCreateNestedManyWithoutUserInput + auditLogs?: Prisma.AuditLogCreateNestedManyWithoutActorInput + submittedTickets?: Prisma.TicketCreateNestedManyWithoutSubmittedByInput +} + +export type UserUncheckedCreateWithoutAssignedTicketsInput = { + id?: string + username: string + email: string + password?: string | null + googleId?: string | null + profile_image_url?: string | null + plan?: $Enums.Plan + role?: $Enums.Role + is_active?: boolean + total_scans?: number + total_reports?: number + twoFactorSecret?: string | null + twoFactorEnabled?: boolean + reset_password_token?: string | null + reset_token_expires?: Date | string | null + createdAt?: Date | string + updatedAt?: Date | string + patients?: Prisma.PatientUncheckedCreateNestedManyWithoutCreated_byInput + scans?: Prisma.ScanUncheckedCreateNestedManyWithoutUploaded_byInput + notifications?: Prisma.NotificationsUncheckedCreateNestedManyWithoutUserInput + emailNotification?: Prisma.EmailNotificationUncheckedCreateNestedOneWithoutUserInput + inAppNotification?: Prisma.InAppNotificationUncheckedCreateNestedOneWithoutUserInput + sessions?: Prisma.SessionUncheckedCreateNestedManyWithoutUserInput + ownedOrg?: Prisma.OrganizationUncheckedCreateNestedOneWithoutOwnerInput + orgMember?: Prisma.OrgMemberUncheckedCreateNestedOneWithoutUserInput + subscription?: Prisma.SubscriptionUncheckedCreateNestedOneWithoutUserInput + payments?: Prisma.PaymentUncheckedCreateNestedManyWithoutUserInput + auditLogs?: Prisma.AuditLogUncheckedCreateNestedManyWithoutActorInput + submittedTickets?: Prisma.TicketUncheckedCreateNestedManyWithoutSubmittedByInput +} + +export type UserCreateOrConnectWithoutAssignedTicketsInput = { + where: Prisma.UserWhereUniqueInput + create: Prisma.XOR +} + +export type UserUpsertWithoutSubmittedTicketsInput = { + update: Prisma.XOR + create: Prisma.XOR + where?: Prisma.UserWhereInput +} + +export type UserUpdateToOneWithWhereWithoutSubmittedTicketsInput = { + where?: Prisma.UserWhereInput + data: Prisma.XOR +} + +export type UserUpdateWithoutSubmittedTicketsInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + username?: Prisma.StringFieldUpdateOperationsInput | string + email?: Prisma.StringFieldUpdateOperationsInput | string + password?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + googleId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + profile_image_url?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + plan?: Prisma.EnumPlanFieldUpdateOperationsInput | $Enums.Plan + role?: Prisma.EnumRoleFieldUpdateOperationsInput | $Enums.Role + is_active?: Prisma.BoolFieldUpdateOperationsInput | boolean + total_scans?: Prisma.IntFieldUpdateOperationsInput | number + total_reports?: Prisma.IntFieldUpdateOperationsInput | number + twoFactorSecret?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + twoFactorEnabled?: Prisma.BoolFieldUpdateOperationsInput | boolean + reset_password_token?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + reset_token_expires?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + patients?: Prisma.PatientUpdateManyWithoutCreated_byNestedInput + scans?: Prisma.ScanUpdateManyWithoutUploaded_byNestedInput + notifications?: Prisma.NotificationsUpdateManyWithoutUserNestedInput + emailNotification?: Prisma.EmailNotificationUpdateOneWithoutUserNestedInput + inAppNotification?: Prisma.InAppNotificationUpdateOneWithoutUserNestedInput + sessions?: Prisma.SessionUpdateManyWithoutUserNestedInput + ownedOrg?: Prisma.OrganizationUpdateOneWithoutOwnerNestedInput + orgMember?: Prisma.OrgMemberUpdateOneWithoutUserNestedInput + subscription?: Prisma.SubscriptionUpdateOneWithoutUserNestedInput + payments?: Prisma.PaymentUpdateManyWithoutUserNestedInput + auditLogs?: Prisma.AuditLogUpdateManyWithoutActorNestedInput + assignedTickets?: Prisma.TicketUpdateManyWithoutAssignedToNestedInput +} + +export type UserUncheckedUpdateWithoutSubmittedTicketsInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + username?: Prisma.StringFieldUpdateOperationsInput | string + email?: Prisma.StringFieldUpdateOperationsInput | string + password?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + googleId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + profile_image_url?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + plan?: Prisma.EnumPlanFieldUpdateOperationsInput | $Enums.Plan + role?: Prisma.EnumRoleFieldUpdateOperationsInput | $Enums.Role + is_active?: Prisma.BoolFieldUpdateOperationsInput | boolean + total_scans?: Prisma.IntFieldUpdateOperationsInput | number + total_reports?: Prisma.IntFieldUpdateOperationsInput | number + twoFactorSecret?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + twoFactorEnabled?: Prisma.BoolFieldUpdateOperationsInput | boolean + reset_password_token?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + reset_token_expires?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + patients?: Prisma.PatientUncheckedUpdateManyWithoutCreated_byNestedInput + scans?: Prisma.ScanUncheckedUpdateManyWithoutUploaded_byNestedInput + notifications?: Prisma.NotificationsUncheckedUpdateManyWithoutUserNestedInput + emailNotification?: Prisma.EmailNotificationUncheckedUpdateOneWithoutUserNestedInput + inAppNotification?: Prisma.InAppNotificationUncheckedUpdateOneWithoutUserNestedInput + sessions?: Prisma.SessionUncheckedUpdateManyWithoutUserNestedInput + ownedOrg?: Prisma.OrganizationUncheckedUpdateOneWithoutOwnerNestedInput + orgMember?: Prisma.OrgMemberUncheckedUpdateOneWithoutUserNestedInput + subscription?: Prisma.SubscriptionUncheckedUpdateOneWithoutUserNestedInput + payments?: Prisma.PaymentUncheckedUpdateManyWithoutUserNestedInput + auditLogs?: Prisma.AuditLogUncheckedUpdateManyWithoutActorNestedInput + assignedTickets?: Prisma.TicketUncheckedUpdateManyWithoutAssignedToNestedInput +} + +export type UserUpsertWithoutAssignedTicketsInput = { + update: Prisma.XOR + create: Prisma.XOR + where?: Prisma.UserWhereInput +} + +export type UserUpdateToOneWithWhereWithoutAssignedTicketsInput = { + where?: Prisma.UserWhereInput + data: Prisma.XOR +} + +export type UserUpdateWithoutAssignedTicketsInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + username?: Prisma.StringFieldUpdateOperationsInput | string + email?: Prisma.StringFieldUpdateOperationsInput | string + password?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + googleId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + profile_image_url?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + plan?: Prisma.EnumPlanFieldUpdateOperationsInput | $Enums.Plan + role?: Prisma.EnumRoleFieldUpdateOperationsInput | $Enums.Role + is_active?: Prisma.BoolFieldUpdateOperationsInput | boolean + total_scans?: Prisma.IntFieldUpdateOperationsInput | number + total_reports?: Prisma.IntFieldUpdateOperationsInput | number + twoFactorSecret?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + twoFactorEnabled?: Prisma.BoolFieldUpdateOperationsInput | boolean + reset_password_token?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + reset_token_expires?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + patients?: Prisma.PatientUpdateManyWithoutCreated_byNestedInput + scans?: Prisma.ScanUpdateManyWithoutUploaded_byNestedInput + notifications?: Prisma.NotificationsUpdateManyWithoutUserNestedInput + emailNotification?: Prisma.EmailNotificationUpdateOneWithoutUserNestedInput + inAppNotification?: Prisma.InAppNotificationUpdateOneWithoutUserNestedInput + sessions?: Prisma.SessionUpdateManyWithoutUserNestedInput + ownedOrg?: Prisma.OrganizationUpdateOneWithoutOwnerNestedInput + orgMember?: Prisma.OrgMemberUpdateOneWithoutUserNestedInput + subscription?: Prisma.SubscriptionUpdateOneWithoutUserNestedInput + payments?: Prisma.PaymentUpdateManyWithoutUserNestedInput + auditLogs?: Prisma.AuditLogUpdateManyWithoutActorNestedInput + submittedTickets?: Prisma.TicketUpdateManyWithoutSubmittedByNestedInput +} + +export type UserUncheckedUpdateWithoutAssignedTicketsInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + username?: Prisma.StringFieldUpdateOperationsInput | string + email?: Prisma.StringFieldUpdateOperationsInput | string + password?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + googleId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + profile_image_url?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + plan?: Prisma.EnumPlanFieldUpdateOperationsInput | $Enums.Plan + role?: Prisma.EnumRoleFieldUpdateOperationsInput | $Enums.Role + is_active?: Prisma.BoolFieldUpdateOperationsInput | boolean + total_scans?: Prisma.IntFieldUpdateOperationsInput | number + total_reports?: Prisma.IntFieldUpdateOperationsInput | number + twoFactorSecret?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + twoFactorEnabled?: Prisma.BoolFieldUpdateOperationsInput | boolean + reset_password_token?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + reset_token_expires?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + patients?: Prisma.PatientUncheckedUpdateManyWithoutCreated_byNestedInput + scans?: Prisma.ScanUncheckedUpdateManyWithoutUploaded_byNestedInput + notifications?: Prisma.NotificationsUncheckedUpdateManyWithoutUserNestedInput + emailNotification?: Prisma.EmailNotificationUncheckedUpdateOneWithoutUserNestedInput + inAppNotification?: Prisma.InAppNotificationUncheckedUpdateOneWithoutUserNestedInput + sessions?: Prisma.SessionUncheckedUpdateManyWithoutUserNestedInput + ownedOrg?: Prisma.OrganizationUncheckedUpdateOneWithoutOwnerNestedInput + orgMember?: Prisma.OrgMemberUncheckedUpdateOneWithoutUserNestedInput + subscription?: Prisma.SubscriptionUncheckedUpdateOneWithoutUserNestedInput + payments?: Prisma.PaymentUncheckedUpdateManyWithoutUserNestedInput + auditLogs?: Prisma.AuditLogUncheckedUpdateManyWithoutActorNestedInput + submittedTickets?: Prisma.TicketUncheckedUpdateManyWithoutSubmittedByNestedInput } export type UserCreateWithoutAuditLogsInput = { @@ -2288,6 +2700,8 @@ export type UserCreateWithoutAuditLogsInput = { orgMember?: Prisma.OrgMemberCreateNestedOneWithoutUserInput subscription?: Prisma.SubscriptionCreateNestedOneWithoutUserInput payments?: Prisma.PaymentCreateNestedManyWithoutUserInput + submittedTickets?: Prisma.TicketCreateNestedManyWithoutSubmittedByInput + assignedTickets?: Prisma.TicketCreateNestedManyWithoutAssignedToInput } export type UserUncheckedCreateWithoutAuditLogsInput = { @@ -2318,6 +2732,8 @@ export type UserUncheckedCreateWithoutAuditLogsInput = { orgMember?: Prisma.OrgMemberUncheckedCreateNestedOneWithoutUserInput subscription?: Prisma.SubscriptionUncheckedCreateNestedOneWithoutUserInput payments?: Prisma.PaymentUncheckedCreateNestedManyWithoutUserInput + submittedTickets?: Prisma.TicketUncheckedCreateNestedManyWithoutSubmittedByInput + assignedTickets?: Prisma.TicketUncheckedCreateNestedManyWithoutAssignedToInput } export type UserCreateOrConnectWithoutAuditLogsInput = { @@ -2364,6 +2780,8 @@ export type UserUpdateWithoutAuditLogsInput = { orgMember?: Prisma.OrgMemberUpdateOneWithoutUserNestedInput subscription?: Prisma.SubscriptionUpdateOneWithoutUserNestedInput payments?: Prisma.PaymentUpdateManyWithoutUserNestedInput + submittedTickets?: Prisma.TicketUpdateManyWithoutSubmittedByNestedInput + assignedTickets?: Prisma.TicketUpdateManyWithoutAssignedToNestedInput } export type UserUncheckedUpdateWithoutAuditLogsInput = { @@ -2394,6 +2812,8 @@ export type UserUncheckedUpdateWithoutAuditLogsInput = { orgMember?: Prisma.OrgMemberUncheckedUpdateOneWithoutUserNestedInput subscription?: Prisma.SubscriptionUncheckedUpdateOneWithoutUserNestedInput payments?: Prisma.PaymentUncheckedUpdateManyWithoutUserNestedInput + submittedTickets?: Prisma.TicketUncheckedUpdateManyWithoutSubmittedByNestedInput + assignedTickets?: Prisma.TicketUncheckedUpdateManyWithoutAssignedToNestedInput } @@ -2408,6 +2828,8 @@ export type UserCountOutputType = { sessions: number payments: number auditLogs: number + submittedTickets: number + assignedTickets: number } export type UserCountOutputTypeSelect = { @@ -2417,6 +2839,8 @@ export type UserCountOutputTypeSelect = { + where?: Prisma.TicketWhereInput +} + +/** + * UserCountOutputType without action + */ +export type UserCountOutputTypeCountAssignedTicketsArgs = { + where?: Prisma.TicketWhereInput +} + export type UserSelect = runtime.Types.Extensions.GetSelect<{ id?: boolean @@ -2501,6 +2939,8 @@ export type UserSelect payments?: boolean | Prisma.User$paymentsArgs auditLogs?: boolean | Prisma.User$auditLogsArgs + submittedTickets?: boolean | Prisma.User$submittedTicketsArgs + assignedTickets?: boolean | Prisma.User$assignedTicketsArgs _count?: boolean | Prisma.UserCountOutputTypeDefaultArgs }, ExtArgs["result"]["user"]> @@ -2577,6 +3017,8 @@ export type UserInclude payments?: boolean | Prisma.User$paymentsArgs auditLogs?: boolean | Prisma.User$auditLogsArgs + submittedTickets?: boolean | Prisma.User$submittedTicketsArgs + assignedTickets?: boolean | Prisma.User$assignedTicketsArgs _count?: boolean | Prisma.UserCountOutputTypeDefaultArgs } export type UserIncludeCreateManyAndReturn = {} @@ -2596,6 +3038,8 @@ export type $UserPayload | null payments: Prisma.$PaymentPayload[] auditLogs: Prisma.$AuditLogPayload[] + submittedTickets: Prisma.$TicketPayload[] + assignedTickets: Prisma.$TicketPayload[] } scalars: runtime.Types.Extensions.GetPayloadResult<{ id: string @@ -3020,6 +3464,8 @@ export interface Prisma__UserClient = {}>(args?: Prisma.Subset>): Prisma.Prisma__SubscriptionClient, T, "findUniqueOrThrow", GlobalOmitOptions> | null, null, ExtArgs, GlobalOmitOptions> payments = {}>(args?: Prisma.Subset>): Prisma.PrismaPromise, T, "findMany", GlobalOmitOptions> | Null> auditLogs = {}>(args?: Prisma.Subset>): Prisma.PrismaPromise, T, "findMany", GlobalOmitOptions> | Null> + submittedTickets = {}>(args?: Prisma.Subset>): Prisma.PrismaPromise, T, "findMany", GlobalOmitOptions> | Null> + assignedTickets = {}>(args?: Prisma.Subset>): Prisma.PrismaPromise, T, "findMany", GlobalOmitOptions> | Null> /** * Attaches callbacks for the resolution and/or rejection of the Promise. * @param onfulfilled The callback to execute when the Promise is resolved. @@ -3697,6 +4143,54 @@ export type User$auditLogsArgs = { + /** + * Select specific fields to fetch from the Ticket + */ + select?: Prisma.TicketSelect | null + /** + * Omit specific fields from the Ticket + */ + omit?: Prisma.TicketOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.TicketInclude | null + where?: Prisma.TicketWhereInput + orderBy?: Prisma.TicketOrderByWithRelationInput | Prisma.TicketOrderByWithRelationInput[] + cursor?: Prisma.TicketWhereUniqueInput + take?: number + skip?: number + distinct?: Prisma.TicketScalarFieldEnum | Prisma.TicketScalarFieldEnum[] +} + +/** + * User.assignedTickets + */ +export type User$assignedTicketsArgs = { + /** + * Select specific fields to fetch from the Ticket + */ + select?: Prisma.TicketSelect | null + /** + * Omit specific fields from the Ticket + */ + omit?: Prisma.TicketOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.TicketInclude | null + where?: Prisma.TicketWhereInput + orderBy?: Prisma.TicketOrderByWithRelationInput | Prisma.TicketOrderByWithRelationInput[] + cursor?: Prisma.TicketWhereUniqueInput + take?: number + skip?: number + distinct?: Prisma.TicketScalarFieldEnum | Prisma.TicketScalarFieldEnum[] +} + /** * User without action */ diff --git a/server/prisma/migrations/20260520164706_super_admin_and_tickets/migration.sql b/server/prisma/migrations/20260520164706_super_admin_and_tickets/migration.sql new file mode 100644 index 0000000..5a5866c --- /dev/null +++ b/server/prisma/migrations/20260520164706_super_admin_and_tickets/migration.sql @@ -0,0 +1,66 @@ +-- CreateEnum +CREATE TYPE "TicketType" AS ENUM ('RE_ANALYSIS', 'RE_REPORT'); + +-- CreateEnum +CREATE TYPE "TicketStatus" AS ENUM ('OPEN', 'IN_PROGRESS', 'RESOLVED', 'DISMISSED'); + +-- CreateEnum +CREATE TYPE "TicketPriority" AS ENUM ('LOW', 'MEDIUM', 'HIGH'); + +-- AlterEnum +ALTER TYPE "Role" ADD VALUE 'SUPER_ADMIN'; + +-- CreateTable +CREATE TABLE "Ticket" ( + "id" TEXT NOT NULL, + "code" TEXT NOT NULL, + "type" "TicketType" NOT NULL, + "status" "TicketStatus" NOT NULL DEFAULT 'OPEN', + "priority" "TicketPriority" NOT NULL DEFAULT 'MEDIUM', + "reason" TEXT NOT NULL, + "scanId" TEXT, + "reportId" TEXT, + "submittedById" TEXT NOT NULL, + "assignedToId" TEXT, + "resolutionNote" TEXT, + "reanalysisScanId" TEXT, + "reanalysisReportId" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "resolvedAt" TIMESTAMP(3), + + CONSTRAINT "Ticket_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE UNIQUE INDEX "Ticket_code_key" ON "Ticket"("code"); + +-- CreateIndex +CREATE INDEX "Ticket_status_idx" ON "Ticket"("status"); + +-- CreateIndex +CREATE INDEX "Ticket_type_idx" ON "Ticket"("type"); + +-- CreateIndex +CREATE INDEX "Ticket_submittedById_idx" ON "Ticket"("submittedById"); + +-- CreateIndex +CREATE INDEX "Ticket_createdAt_idx" ON "Ticket"("createdAt"); + +-- AddForeignKey +ALTER TABLE "Ticket" ADD CONSTRAINT "Ticket_scanId_fkey" FOREIGN KEY ("scanId") REFERENCES "Scan"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Ticket" ADD CONSTRAINT "Ticket_reportId_fkey" FOREIGN KEY ("reportId") REFERENCES "Report"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Ticket" ADD CONSTRAINT "Ticket_submittedById_fkey" FOREIGN KEY ("submittedById") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Ticket" ADD CONSTRAINT "Ticket_assignedToId_fkey" FOREIGN KEY ("assignedToId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Ticket" ADD CONSTRAINT "Ticket_reanalysisScanId_fkey" FOREIGN KEY ("reanalysisScanId") REFERENCES "Scan"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Ticket" ADD CONSTRAINT "Ticket_reanalysisReportId_fkey" FOREIGN KEY ("reanalysisReportId") REFERENCES "Report"("id") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/server/prisma/migrations/20260520172537_audit_log_org_nullable/migration.sql b/server/prisma/migrations/20260520172537_audit_log_org_nullable/migration.sql new file mode 100644 index 0000000..71abb02 --- /dev/null +++ b/server/prisma/migrations/20260520172537_audit_log_org_nullable/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "AuditLog" ALTER COLUMN "orgId" DROP NOT NULL; diff --git a/server/prisma/schema.prisma b/server/prisma/schema.prisma index c0bf676..bea4f47 100644 --- a/server/prisma/schema.prisma +++ b/server/prisma/schema.prisma @@ -11,7 +11,7 @@ generator client { // User enum Role { USER - ADMIN + SUPER_ADMIN } enum Plan { FREE @@ -56,6 +56,9 @@ model User { payments Payment[] auditLogs AuditLog[] + + submittedTickets Ticket[] @relation("TicketSubmittedBy") + assignedTickets Ticket[] @relation("TicketAssignedTo") } // HOSPITAL @@ -153,6 +156,9 @@ model Scan { // Relations scanImage ScanImage? report Report? + + ticketsForScan Ticket[] @relation("TicketScan") + ticketsAsReanalysis Ticket[] @relation("TicketReanalysisScan") } model ScanImage { @@ -184,6 +190,9 @@ model Report { createdAt DateTime @default(now()) updatedAt DateTime @updatedAt + + ticketsForReport Ticket[] @relation("TicketReport") + ticketsAsReanalysis Ticket[] @relation("TicketReanalysisReport") } // Notification @@ -309,6 +318,58 @@ model Payment { user User @relation(fields: [userId], references: [id], onDelete: Cascade) } +// Tickets +enum TicketType { + RE_ANALYSIS + RE_REPORT +} +enum TicketStatus { + OPEN + IN_PROGRESS + RESOLVED + DISMISSED +} +enum TicketPriority { + LOW + MEDIUM + HIGH +} +model Ticket { + id String @id @default(uuid()) + code String @unique + type TicketType + status TicketStatus @default(OPEN) + priority TicketPriority @default(MEDIUM) + reason String + + scanId String? + scan Scan? @relation("TicketScan", fields: [scanId], references: [id], onDelete: SetNull) + + reportId String? + report Report? @relation("TicketReport", fields: [reportId], references: [id], onDelete: SetNull) + + submittedById String + submittedBy User @relation("TicketSubmittedBy", fields: [submittedById], references: [id], onDelete: Cascade) + + assignedToId String? + assignedTo User? @relation("TicketAssignedTo", fields: [assignedToId], references: [id], onDelete: SetNull) + + resolutionNote String? + reanalysisScanId String? + reanalysisScan Scan? @relation("TicketReanalysisScan", fields: [reanalysisScanId], references: [id], onDelete: SetNull) + reanalysisReportId String? + reanalysisReport Report? @relation("TicketReanalysisReport", fields: [reanalysisReportId], references: [id], onDelete: SetNull) + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + resolvedAt DateTime? + + @@index([status]) + @@index([type]) + @@index([submittedById]) + @@index([createdAt]) +} + // Audit Logs enum AuditCategory { scans @@ -330,8 +391,8 @@ enum AuditStatus { model AuditLog { id String @id @default(uuid()) - orgId String - organization Organization @relation(fields: [orgId], references: [id], onDelete: Cascade) + orgId String? + organization Organization? @relation(fields: [orgId], references: [id], onDelete: Cascade) actorId String? actor User? @relation(fields: [actorId], references: [id], onDelete: SetNull) diff --git a/server/src/Notifications/notifications.listener.ts b/server/src/Notifications/notifications.listener.ts index 7abcd70..ffe3692 100644 --- a/server/src/Notifications/notifications.listener.ts +++ b/server/src/Notifications/notifications.listener.ts @@ -55,10 +55,13 @@ export class NotificationsListener { private async dispatch(payload: { userId: string; type: string; - payload: { + payload: { scanId?: string; reportId?: string; - status?: boolean + status?: boolean; + ticketCode?: string; + ticketType?: 'RE_ANALYSIS' | 'RE_REPORT'; + resolutionNote?: string | null; }; }) { @@ -148,6 +151,35 @@ export class NotificationsListener { } } + // Ticket Resolved / Dismissed + if (payload.type === 'TICKET_RESOLVED' || payload.type === 'TICKET_DISMISSED') { + const resolved = payload.type === 'TICKET_RESOLVED'; + const ticketCode = payload.payload.ticketCode; + const ticketType = payload.payload.ticketType; + if (!ticketCode) return; + + const subject = ticketType === 'RE_REPORT' ? 'report re-generation' : 'scan re-analysis'; + const message = resolved + ? `DONE — your ${subject} request (${ticketCode}) has been completed.${ + payload.payload.resolutionNote ? ` Note: ${payload.payload.resolutionNote}` : '' + }` + : `Your ${subject} request (${ticketCode}) was dismissed.${ + payload.payload.resolutionNote ? ` Note: ${payload.payload.resolutionNote}` : '' + }`; + + const notif = await this.prisma.notifications.create({ + data: { + userId: payload.userId, + type: resolved ? 'report' : 'alert', + title: resolved ? 'Request Completed' : 'Request Dismissed', + message, + path: null, + }, + }); + this.stream.push(payload.userId, notif); + return; + } + // Active/Inactive Org Member if(payload.type == 'ORG_MEMBER_STATUS_CHANGE') { const userId = payload.userId; diff --git a/server/src/Organization/audit-log.service.ts b/server/src/Organization/audit-log.service.ts index c440fb5..f8aa191 100644 --- a/server/src/Organization/audit-log.service.ts +++ b/server/src/Organization/audit-log.service.ts @@ -86,6 +86,169 @@ export class AuditLogService { return null; } + // Super-admin actions: writes a global audit log row (orgId nullable). + // If targetUserId is provided and that user belongs to an ORGANIZATION-plan org, + // the row is attributed to that org so it also shows up in the org's audit view. + async logAsSuperAdmin(input: AuditLogInput & { targetUserId?: string | null }) { + try { + const userId = this.request.user?.userId; + if (!userId) return null; + + const actor = await this.prisma.user.findUnique({ + where: { id: userId }, + select: { id: true, username: true, email: true, role: true }, + }); + if (!actor || actor.role !== 'SUPER_ADMIN') return null; + + let orgId: string | null = null; + if (input.targetUserId) { + const target = await this.prisma.user.findUnique({ + where: { id: input.targetUserId }, + include: { + ownedOrg: { select: { id: true, owner: { select: { plan: true } } } }, + orgMember: { + include: { + org: { include: { owner: { select: { plan: true } } } }, + }, + }, + }, + }); + if (target?.ownedOrg && target.plan === 'ORGANIZATION') { + orgId = target.ownedOrg.id; + } else if (target?.orgMember?.org?.owner?.plan === 'ORGANIZATION') { + orgId = target.orgMember.org.id; + } + } + + return await this.prisma.auditLog.create({ + data: { + orgId: orgId ?? undefined, + actorId: actor.id, + actorName: actor.username, + actorEmail: actor.email, + action: input.action, + category: input.category, + target: input.target, + targetId: input.targetId ?? null, + status: input.status ?? 'success', + severity: input.severity ?? 'info', + ip: this.getClientIp(), + userAgent: this.getUserAgent(), + }, + }); + } catch (err) { + console.error('[audit] failed to write super-admin log', err); + return null; + } + } + + // Global audit log listing for super-admin (no org filter). + async listGlobal(filters: AuditLogFilters) { + const page = Math.max(1, Number(filters.page) || 1); + const pageSize = Math.min(100, Math.max(1, Number(filters.pageSize) || 25)); + const where: any = {}; + if (filters.category && filters.category !== 'all') where.category = filters.category; + if (filters.status && filters.status !== 'all') where.status = filters.status; + if (filters.from || filters.to) { + where.createdAt = {}; + if (filters.from) where.createdAt.gte = new Date(filters.from); + if (filters.to) where.createdAt.lte = new Date(filters.to); + } + const s = filters.search?.trim(); + if (s) { + where.OR = [ + { action: { contains: s, mode: 'insensitive' } }, + { actorName: { contains: s, mode: 'insensitive' } }, + { actorEmail: { contains: s, mode: 'insensitive' } }, + { target: { contains: s, mode: 'insensitive' } }, + { ip: { contains: s, mode: 'insensitive' } }, + ]; + } + + const [items, total] = await this.prisma.$transaction([ + this.prisma.auditLog.findMany({ + where, + orderBy: { createdAt: 'desc' }, + skip: (page - 1) * pageSize, + take: pageSize, + include: { + organization: { select: { id: true, name: true } }, + }, + }), + this.prisma.auditLog.count({ where }), + ]); + + return { items, total, page, pageSize }; + } + + async exportGlobalCsv(filters: AuditLogFilters) { + const where: any = {}; + if (filters.category && filters.category !== 'all') where.category = filters.category; + if (filters.status && filters.status !== 'all') where.status = filters.status; + if (filters.from || filters.to) { + where.createdAt = {}; + if (filters.from) where.createdAt.gte = new Date(filters.from); + if (filters.to) where.createdAt.lte = new Date(filters.to); + } + const s = filters.search?.trim(); + if (s) { + where.OR = [ + { action: { contains: s, mode: 'insensitive' } }, + { actorName: { contains: s, mode: 'insensitive' } }, + { actorEmail: { contains: s, mode: 'insensitive' } }, + { target: { contains: s, mode: 'insensitive' } }, + { ip: { contains: s, mode: 'insensitive' } }, + ]; + } + + const items = await this.prisma.auditLog.findMany({ + where, + orderBy: { createdAt: 'desc' }, + take: 10000, + include: { organization: { select: { name: true } } }, + }); + + const cols = [ + 'timestamp', + 'org', + 'actor_name', + 'actor_email', + 'action', + 'category', + 'status', + 'severity', + 'target', + 'ip', + 'user_agent', + ]; + const escape = (v: unknown) => { + if (v === null || v === undefined) return ''; + const s = typeof v === 'string' ? v : JSON.stringify(v); + return /[",\n]/.test(s) ? `"${s.replace(/"/g, '""')}"` : s; + }; + const lines = [cols.join(',')]; + for (const log of items) { + lines.push( + [ + log.createdAt.toISOString(), + log.organization?.name ?? '', + log.actorName, + log.actorEmail, + log.action, + log.category, + log.status, + log.severity, + log.target, + log.ip ?? '', + log.userAgent ?? '', + ] + .map(escape) + .join(','), + ); + } + return lines.join('\n'); + } + // Main logging function async log(input: AuditLogInput) { try { diff --git a/server/src/Report/report.controller.ts b/server/src/Report/report.controller.ts index e632151..e1110c3 100644 --- a/server/src/Report/report.controller.ts +++ b/server/src/Report/report.controller.ts @@ -7,6 +7,7 @@ import { Post, Delete } from '@nestjs/common'; +import { IsString, IsOptional, IsEnum, MinLength, MaxLength } from 'class-validator'; import { ReportService } from './report.service'; import { JwtAccessGuard } from 'src/auth/guards/jwt-access.guard'; import { PlanGuard } from 'src/auth/guards/plan.guard'; @@ -14,6 +15,18 @@ import { RequirePlan, RestrictOrgMember, } from 'src/auth/decorators/require-plan.decorator'; +import { TicketPriority } from '../../prisma/generated/client/enums'; + +class FlagReportDto { + @IsString() + @MinLength(3) + @MaxLength(2000) + reason!: string; + + @IsOptional() + @IsEnum(TicketPriority) + priority?: TicketPriority; +} @Controller('report') export class ReportController { @@ -70,4 +83,14 @@ export class ReportController { async deleteReport(@Param('id') id: string) { return this.reportService.deleteReport(id); } + + // Flag a report for re-generation (creates support ticket) + @UseGuards(JwtAccessGuard) + @Post(':code/flag') + async flagReport( + @Param('code') code: string, + @Body() body: FlagReportDto, + ) { + return this.reportService.flagReport(code, body); + } } diff --git a/server/src/Report/report.service.ts b/server/src/Report/report.service.ts index 8f4d2f0..f9ac15b 100644 --- a/server/src/Report/report.service.ts +++ b/server/src/Report/report.service.ts @@ -1,12 +1,14 @@ -import { Injectable, Scope, Inject } from '@nestjs/common'; +import { Injectable, Scope, Inject, NotFoundException, ForbiddenException } from '@nestjs/common'; import { InjectQueue } from '@nestjs/bullmq'; import { Queue } from 'bullmq'; import { REQUEST } from '@nestjs/core'; import type { Request } from 'express'; +import { randomBytes } from 'crypto'; import { PrismaService } from '../../prisma/prisma.service'; import { OrganizationService } from 'src/Organization/organization.service'; import { AuditLogService } from 'src/Organization/audit-log.service'; import { REPORT_QUEUE, ReportJobData } from './report.processor'; +import { TicketType, TicketPriority } from '../../prisma/generated/client/enums'; type RequestUser = { userId?: string; @@ -319,4 +321,60 @@ export class ReportService { message: "Report deleted successfully.", }; } + + // Flag a report for re-generation (creates a support ticket) + async flagReport( + code: string, + body: { reason: string; priority?: TicketPriority }, + ) { + const userId = this.organizationService.getUserId(); + + const report = await this.prisma.report.findUnique({ + where: { code }, + include: { scan: { include: { patient: true } } }, + }); + if (!report) throw new NotFoundException('Report not found'); + + const isOwner = report.scan.uploadedById === userId; + let hasOrgAccess = false; + if (!isOwner && report.scan.orgId) { + const org = await this.prisma.organization.findFirst({ + where: { + id: report.scan.orgId, + OR: [ + { ownerId: userId }, + { members: { some: { userId } } }, + ], + }, + }); + hasOrgAccess = !!org; + } + if (!isOwner && !hasOrgAccess) { + throw new ForbiddenException('Not authorized'); + } + + const ticketCode = `TKT-${randomBytes(3).toString('hex').toUpperCase()}`; + const ticket = await this.prisma.ticket.create({ + data: { + code: ticketCode, + type: TicketType.RE_REPORT, + priority: body.priority ?? TicketPriority.MEDIUM, + reason: body.reason, + scanId: report.scanId, + reportId: report.id, + submittedById: userId, + }, + select: { code: true, status: true, createdAt: true }, + }); + + await this.auditLog.log({ + action: 'report.flagged', + category: 'reports', + target: `${report.code} · ${ticket.code}`, + targetId: report.id, + severity: 'warning', + }); + + return { success: true, ticket }; + } } \ No newline at end of file diff --git a/server/src/ScanResult/scan_result.controller.ts b/server/src/ScanResult/scan_result.controller.ts index ae5cdf0..71b3a9d 100644 --- a/server/src/ScanResult/scan_result.controller.ts +++ b/server/src/ScanResult/scan_result.controller.ts @@ -6,7 +6,10 @@ import { Param, Delete, Patch, + Post, } from '@nestjs/common'; +import { IsString, IsOptional, IsEnum, MinLength, MaxLength } from 'class-validator'; +import { TicketPriority } from '../../prisma/generated/client/enums'; import { ScanResultService } from './scan_result.service'; import { JwtAccessGuard } from 'src/auth/guards/jwt-access.guard'; import { PlanGuard } from 'src/auth/guards/plan.guard'; @@ -15,6 +18,17 @@ import { RestrictOrgMember, } from 'src/auth/decorators/require-plan.decorator'; +class FlagScanDto { + @IsString() + @MinLength(3) + @MaxLength(2000) + reason!: string; + + @IsOptional() + @IsEnum(TicketPriority) + priority?: TicketPriority; +} + @Controller('scan-result') export class ScanResultController { constructor(private scanResultService: ScanResultService) {} @@ -49,4 +63,14 @@ export class ScanResultController { async deleteScanResult(@Param('resultId') resultId: string) { return this.scanResultService.deleteScanResult(resultId); } + + // Flag scan for re-analysis (creates support ticket) + @UseGuards(JwtAccessGuard) + @Post(':resultId/flag') + async flagScan( + @Param('resultId') resultId: string, + @Body() body: FlagScanDto, + ) { + return this.scanResultService.flagScan(resultId, body); + } } diff --git a/server/src/ScanResult/scan_result.service.ts b/server/src/ScanResult/scan_result.service.ts index f0aa67e..a199d6e 100644 --- a/server/src/ScanResult/scan_result.service.ts +++ b/server/src/ScanResult/scan_result.service.ts @@ -1,7 +1,9 @@ -import { Injectable } from '@nestjs/common'; +import { Injectable, NotFoundException, ForbiddenException } from '@nestjs/common'; +import { randomBytes } from 'crypto'; import { PrismaService } from '../../prisma/prisma.service'; import { OrganizationService } from 'src/Organization/organization.service'; import { AuditLogService } from 'src/Organization/audit-log.service'; +import { TicketType, TicketPriority } from '../../prisma/generated/client/enums'; @Injectable() export class ScanResultService { @@ -11,6 +13,57 @@ export class ScanResultService { private auditLog: AuditLogService, ) {} + // Flag a scan for re-analysis (creates a support ticket) + async flagScan( + resultId: string, + body: { reason: string; priority?: TicketPriority }, + ) { + const userId = this.organizationService.getUserId(); + + const scan = await this.prisma.scan.findUnique({ + where: { id: resultId }, + include: { report: true }, + }); + if (!scan) throw new NotFoundException('Scan not found'); + + // Only the uploader (or org members for org scans) can flag. + if (scan.uploadedById !== userId) { + const orgId = scan.orgId; + if (!orgId) throw new ForbiddenException('Not authorized'); + const member = await this.prisma.orgMember.findFirst({ + where: { userId, orgId }, + }); + const isOwner = await this.prisma.organization.findFirst({ + where: { id: orgId, ownerId: userId }, + }); + if (!member && !isOwner) throw new ForbiddenException('Not authorized'); + } + + const code = `TKT-${randomBytes(3).toString('hex').toUpperCase()}`; + const ticket = await this.prisma.ticket.create({ + data: { + code, + type: TicketType.RE_ANALYSIS, + priority: body.priority ?? TicketPriority.MEDIUM, + reason: body.reason, + scanId: scan.id, + reportId: scan.report?.id ?? null, + submittedById: userId, + }, + select: { code: true, status: true, createdAt: true }, + }); + + await this.auditLog.log({ + action: 'scan.flagged', + category: 'scans', + target: `${scan.scan_code} · ${ticket.code}`, + targetId: scan.id, + severity: 'warning', + }); + + return { success: true, ticket }; + } + // Scan List async getScanResults() { const userId = this.organizationService.getUserId(); diff --git a/server/src/SuperAdmin/controllers/audit.controller.ts b/server/src/SuperAdmin/controllers/audit.controller.ts new file mode 100644 index 0000000..7e406c7 --- /dev/null +++ b/server/src/SuperAdmin/controllers/audit.controller.ts @@ -0,0 +1,29 @@ +import { Controller, Get, Query, Res, UseGuards } from '@nestjs/common'; +import type { Response } from 'express'; +import { JwtAccessGuard } from '../../auth/guards/jwt-access.guard'; +import { SuperAdminGuard } from '../guards/super-admin.guard'; +import { AuditLogService } from '../../Organization/audit-log.service'; +import type { AuditLogFilters } from '../../Organization/audit-log.service'; + +@Controller('superadmin/audit-logs') +@UseGuards(JwtAccessGuard, SuperAdminGuard) +export class AuditAdminController { + constructor(private auditLogService: AuditLogService) {} + + @Get() + async list(@Query() query: AuditLogFilters) { + return this.auditLogService.listGlobal(query); + } + + @Get('export') + async exportCsv(@Query() query: AuditLogFilters, @Res() res: Response) { + const csv = await this.auditLogService.exportGlobalCsv(query); + const stamp = new Date().toISOString().slice(0, 10); + res.setHeader('Content-Type', 'text/csv; charset=utf-8'); + res.setHeader( + 'Content-Disposition', + `attachment; filename="audit-logs-${stamp}.csv"`, + ); + res.send(csv); + } +} diff --git a/server/src/SuperAdmin/controllers/billing.controller.ts b/server/src/SuperAdmin/controllers/billing.controller.ts new file mode 100644 index 0000000..30a74bc --- /dev/null +++ b/server/src/SuperAdmin/controllers/billing.controller.ts @@ -0,0 +1,43 @@ +import { + Controller, + Get, + Post, + Param, + Query, + UseGuards, +} from '@nestjs/common'; +import { JwtAccessGuard } from '../../auth/guards/jwt-access.guard'; +import { SuperAdminGuard } from '../guards/super-admin.guard'; +import { BillingAdminService } from '../services/billing.service'; +import { ListSubscriptionsDto } from '../dto/billing.dto'; + +@Controller('superadmin/billing') +@UseGuards(JwtAccessGuard, SuperAdminGuard) +export class BillingAdminController { + constructor(private billingService: BillingAdminService) {} + + @Get('kpis') + async kpis() { + return this.billingService.kpis(); + } + + @Get('subscriptions') + async listSubscriptions(@Query() query: ListSubscriptionsDto) { + return this.billingService.listSubscriptions(query); + } + + @Post('subscriptions/:id/sync') + async sync(@Param('id') stripeSubscriptionId: string) { + return this.billingService.syncFromStripe(stripeSubscriptionId); + } + + @Post('subscriptions/:id/cancel') + async cancel(@Param('id') stripeSubscriptionId: string) { + return this.billingService.cancel(stripeSubscriptionId); + } + + @Get('payments') + async recentPayments(@Query('limit') limit?: string) { + return this.billingService.recentPayments(limit ? Number(limit) : 20); + } +} diff --git a/server/src/SuperAdmin/controllers/overview.controller.ts b/server/src/SuperAdmin/controllers/overview.controller.ts new file mode 100644 index 0000000..429c11a --- /dev/null +++ b/server/src/SuperAdmin/controllers/overview.controller.ts @@ -0,0 +1,15 @@ +import { Controller, Get, UseGuards } from '@nestjs/common'; +import { JwtAccessGuard } from '../../auth/guards/jwt-access.guard'; +import { SuperAdminGuard } from '../guards/super-admin.guard'; +import { OverviewService } from '../services/overview.service'; + +@Controller('superadmin/overview') +@UseGuards(JwtAccessGuard, SuperAdminGuard) +export class OverviewController { + constructor(private overviewService: OverviewService) {} + + @Get() + async getOverview() { + return this.overviewService.getOverview(); + } +} diff --git a/server/src/SuperAdmin/controllers/tickets.controller.ts b/server/src/SuperAdmin/controllers/tickets.controller.ts new file mode 100644 index 0000000..c987705 --- /dev/null +++ b/server/src/SuperAdmin/controllers/tickets.controller.ts @@ -0,0 +1,60 @@ +import { + Controller, + Get, + Post, + Patch, + Body, + Param, + Query, + UseGuards, +} from '@nestjs/common'; +import { JwtAccessGuard } from '../../auth/guards/jwt-access.guard'; +import { SuperAdminGuard } from '../guards/super-admin.guard'; +import { TicketsAdminService } from '../services/tickets.service'; +import { + ListTicketsDto, + AssignTicketDto, + ResolveTicketDto, + DismissTicketDto, +} from '../dto/ticket.dto'; + +@Controller('superadmin/tickets') +@UseGuards(JwtAccessGuard, SuperAdminGuard) +export class TicketsAdminController { + constructor(private ticketsService: TicketsAdminService) {} + + @Get() + async list(@Query() query: ListTicketsDto) { + return this.ticketsService.list(query); + } + + @Get(':code') + async detail(@Param('code') code: string) { + return this.ticketsService.detail(code); + } + + @Patch(':code/assign') + async assign(@Param('code') code: string, @Body() body: AssignTicketDto) { + return this.ticketsService.assign(code, body.assignedToId); + } + + @Post(':code/reanalyze') + async reanalyze(@Param('code') code: string) { + return this.ticketsService.reanalyze(code); + } + + @Post(':code/regenerate') + async regenerate(@Param('code') code: string) { + return this.ticketsService.regenerate(code); + } + + @Patch(':code/resolve') + async resolve(@Param('code') code: string, @Body() body: ResolveTicketDto) { + return this.ticketsService.resolve(code, body.resolutionNote); + } + + @Patch(':code/dismiss') + async dismiss(@Param('code') code: string, @Body() body: DismissTicketDto) { + return this.ticketsService.dismiss(code, body.resolutionNote); + } +} diff --git a/server/src/SuperAdmin/controllers/users.controller.ts b/server/src/SuperAdmin/controllers/users.controller.ts new file mode 100644 index 0000000..1b2153d --- /dev/null +++ b/server/src/SuperAdmin/controllers/users.controller.ts @@ -0,0 +1,67 @@ +import { + Controller, + Get, + Patch, + Post, + Delete, + Param, + Query, + Body, + UseGuards, +} from '@nestjs/common'; +import { JwtAccessGuard } from '../../auth/guards/jwt-access.guard'; +import { SuperAdminGuard } from '../guards/super-admin.guard'; +import { UsersAdminService } from '../services/users.service'; +import { ListUsersDto, PaginationDto } from '../dto/list-users.dto'; +import { UpdateUserStatusDto } from '../dto/update-user-status.dto'; + +@Controller('superadmin/users') +@UseGuards(JwtAccessGuard, SuperAdminGuard) +export class UsersAdminController { + constructor(private usersService: UsersAdminService) {} + + @Get() + async list(@Query() query: ListUsersDto) { + return this.usersService.list(query); + } + + @Get(':id') + async getProfile(@Param('id') id: string) { + return this.usersService.getProfile(id); + } + + @Get(':id/scans') + async getScans(@Param('id') id: string, @Query() q: PaginationDto) { + return this.usersService.getScans(id, q.page, q.pageSize); + } + + @Get(':id/reports') + async getReports(@Param('id') id: string, @Query() q: PaginationDto) { + return this.usersService.getReports(id, q.page, q.pageSize); + } + + @Get(':id/patients') + async getPatients(@Param('id') id: string, @Query() q: PaginationDto) { + return this.usersService.getPatients(id, q.page, q.pageSize); + } + + @Get(':id/organization') + async getOrganization(@Param('id') id: string) { + return this.usersService.getOrganization(id); + } + + @Patch(':id/status') + async setStatus(@Param('id') id: string, @Body() body: UpdateUserStatusDto) { + return this.usersService.setStatus(id, body.is_active); + } + + @Post(':id/force-reset') + async forceReset(@Param('id') id: string) { + return this.usersService.forceReset(id); + } + + @Delete(':id') + async softDelete(@Param('id') id: string) { + return this.usersService.softDelete(id); + } +} diff --git a/server/src/SuperAdmin/decorators/require-role.decorator.ts b/server/src/SuperAdmin/decorators/require-role.decorator.ts new file mode 100644 index 0000000..f383efd --- /dev/null +++ b/server/src/SuperAdmin/decorators/require-role.decorator.ts @@ -0,0 +1,6 @@ +import { SetMetadata } from '@nestjs/common'; +import { Role } from '../../../prisma/generated/client/enums'; + +export const REQUIRE_ROLE_KEY = 'require_role'; +export const RequireRole = (...roles: Role[]) => + SetMetadata(REQUIRE_ROLE_KEY, roles); diff --git a/server/src/SuperAdmin/dto/billing.dto.ts b/server/src/SuperAdmin/dto/billing.dto.ts new file mode 100644 index 0000000..8d05ccc --- /dev/null +++ b/server/src/SuperAdmin/dto/billing.dto.ts @@ -0,0 +1,30 @@ +import { IsOptional, IsString, IsEnum, IsInt, Min, Max } from 'class-validator'; +import { Type } from 'class-transformer'; +import { SubscriptionStatus } from '../../../prisma/generated/client/enums'; + +export class ListSubscriptionsDto { + @IsOptional() + @IsEnum(SubscriptionStatus) + status?: SubscriptionStatus; + + @IsOptional() + @IsString() + plan?: 'DOCTOR' | 'ORGANIZATION'; + + @IsOptional() + @IsString() + q?: string; + + @IsOptional() + @Type(() => Number) + @IsInt() + @Min(1) + page?: number; + + @IsOptional() + @Type(() => Number) + @IsInt() + @Min(1) + @Max(100) + pageSize?: number; +} diff --git a/server/src/SuperAdmin/dto/list-users.dto.ts b/server/src/SuperAdmin/dto/list-users.dto.ts new file mode 100644 index 0000000..ea7b3b9 --- /dev/null +++ b/server/src/SuperAdmin/dto/list-users.dto.ts @@ -0,0 +1,53 @@ +import { IsOptional, IsString, IsEnum, IsBooleanString, IsInt, Min, Max } from 'class-validator'; +import { Type } from 'class-transformer'; +import { Plan, Role } from '../../../prisma/generated/client/enums'; + +export class ListUsersDto { + @IsOptional() + @IsEnum(Plan) + plan?: Plan; + + @IsOptional() + @IsEnum(Role) + role?: Role; + + @IsOptional() + @IsString() + status?: 'active' | 'inactive'; + + @IsOptional() + @IsBooleanString() + hasOrg?: string; + + @IsOptional() + @IsString() + q?: string; + + @IsOptional() + @Type(() => Number) + @IsInt() + @Min(1) + page?: number; + + @IsOptional() + @Type(() => Number) + @IsInt() + @Min(1) + @Max(100) + pageSize?: number; +} + +export class PaginationDto { + @IsOptional() + @Type(() => Number) + @IsInt() + @Min(1) + page?: number; + + @IsOptional() + @Type(() => Number) + @IsInt() + @Min(1) + @Max(100) + pageSize?: number; +} diff --git a/server/src/SuperAdmin/dto/ticket.dto.ts b/server/src/SuperAdmin/dto/ticket.dto.ts new file mode 100644 index 0000000..b6ceecb --- /dev/null +++ b/server/src/SuperAdmin/dto/ticket.dto.ts @@ -0,0 +1,67 @@ +import { IsOptional, IsString, IsEnum, IsInt, Min, Max, MaxLength, MinLength } from 'class-validator'; +import { Type } from 'class-transformer'; +import { TicketStatus, TicketType, TicketPriority } from '../../../prisma/generated/client/enums'; + +export class ListTicketsDto { + @IsOptional() + @IsEnum(TicketStatus) + status?: TicketStatus; + + @IsOptional() + @IsEnum(TicketType) + type?: TicketType; + + @IsOptional() + @IsEnum(TicketPriority) + priority?: TicketPriority; + + @IsOptional() + @IsString() + q?: string; + + @IsOptional() + @Type(() => Number) + @IsInt() + @Min(1) + page?: number; + + @IsOptional() + @Type(() => Number) + @IsInt() + @Min(1) + @Max(100) + pageSize?: number; +} + +export class AssignTicketDto { + @IsString() + assignedToId!: string; +} + +export class ResolveTicketDto { + @IsString() + @MinLength(3) + @MaxLength(2000) + resolutionNote!: string; +} + +export class DismissTicketDto { + @IsOptional() + @IsString() + @MaxLength(2000) + resolutionNote?: string; +} + +export class FlagTicketDto { + @IsEnum(TicketType) + type!: TicketType; + + @IsOptional() + @IsEnum(TicketPriority) + priority?: TicketPriority; + + @IsString() + @MinLength(3) + @MaxLength(2000) + reason!: string; +} diff --git a/server/src/SuperAdmin/dto/update-user-status.dto.ts b/server/src/SuperAdmin/dto/update-user-status.dto.ts new file mode 100644 index 0000000..b9bba58 --- /dev/null +++ b/server/src/SuperAdmin/dto/update-user-status.dto.ts @@ -0,0 +1,6 @@ +import { IsBoolean } from 'class-validator'; + +export class UpdateUserStatusDto { + @IsBoolean() + is_active!: boolean; +} diff --git a/server/src/SuperAdmin/guards/super-admin.guard.ts b/server/src/SuperAdmin/guards/super-admin.guard.ts new file mode 100644 index 0000000..53deade --- /dev/null +++ b/server/src/SuperAdmin/guards/super-admin.guard.ts @@ -0,0 +1,44 @@ +import { + CanActivate, + ExecutionContext, + ForbiddenException, + Injectable, +} from '@nestjs/common'; +import { Reflector } from '@nestjs/core'; +import { PrismaService } from '../../../prisma/prisma.service'; +import { Role } from '../../../prisma/generated/client/enums'; +import { REQUIRE_ROLE_KEY } from '../decorators/require-role.decorator'; + +@Injectable() +export class SuperAdminGuard implements CanActivate { + constructor( + private prisma: PrismaService, + private reflector: Reflector, + ) {} + + async canActivate(context: ExecutionContext): Promise { + const required = this.reflector.getAllAndOverride( + REQUIRE_ROLE_KEY, + [context.getHandler(), context.getClass()], + ); + const requiredRoles = required?.length ? required : [Role.SUPER_ADMIN]; + + const request = context.switchToHttp().getRequest(); + const userId = request.user?.userId; + if (!userId) throw new ForbiddenException('Not authenticated'); + + const user = await this.prisma.user.findUnique({ + where: { id: userId }, + select: { role: true, is_active: true }, + }); + if (!user || !user.is_active) { + throw new ForbiddenException('User not found or inactive'); + } + + if (!requiredRoles.includes(user.role)) { + throw new ForbiddenException('Insufficient role'); + } + + return true; + } +} diff --git a/server/src/SuperAdmin/services/billing.service.ts b/server/src/SuperAdmin/services/billing.service.ts new file mode 100644 index 0000000..63f1863 --- /dev/null +++ b/server/src/SuperAdmin/services/billing.service.ts @@ -0,0 +1,159 @@ +import { Injectable, NotFoundException } from '@nestjs/common'; +import { PrismaService } from '../../../prisma/prisma.service'; +import { StripeService } from '../../Stripe/stripe.service'; +import { AuditLogService } from '../../Organization/audit-log.service'; +import { ListSubscriptionsDto } from '../dto/billing.dto'; +import { SubscriptionStatus } from '../../../prisma/generated/client/enums'; + +@Injectable() +export class BillingAdminService { + constructor( + private prisma: PrismaService, + private stripeService: StripeService, + private auditLog: AuditLogService, + ) {} + + async listSubscriptions(filters: ListSubscriptionsDto) { + const page = Math.max(1, Number(filters.page) || 1); + const pageSize = Math.min(100, Math.max(1, Number(filters.pageSize) || 25)); + + const where: any = {}; + if (filters.status) where.status = filters.status; + if (filters.plan) where.user = { plan: filters.plan }; + const q = filters.q?.trim(); + if (q) { + where.user = { + ...(where.user ?? {}), + OR: [ + { email: { contains: q, mode: 'insensitive' } }, + { username: { contains: q, mode: 'insensitive' } }, + ], + }; + } + + const [items, total] = await this.prisma.$transaction([ + this.prisma.subscription.findMany({ + where, + orderBy: { createdAt: 'desc' }, + skip: (page - 1) * pageSize, + take: pageSize, + include: { + user: { + select: { + id: true, + username: true, + email: true, + plan: true, + profile_image_url: true, + }, + }, + }, + }), + this.prisma.subscription.count({ where }), + ]); + + return { items, total, page, pageSize }; + } + + async kpis() { + const day = 24 * 60 * 60 * 1000; + const start30 = new Date(Date.now() - 30 * day); + + const [activeDoctor, activeOrg, pastDue, canceled, mrrPayments] = + await this.prisma.$transaction([ + this.prisma.subscription.count({ + where: { status: 'active', user: { plan: 'DOCTOR' } }, + }), + this.prisma.subscription.count({ + where: { status: 'active', user: { plan: 'ORGANIZATION' } }, + }), + this.prisma.subscription.count({ where: { status: 'past_due' } }), + this.prisma.subscription.count({ where: { status: 'canceled' } }), + this.prisma.payment.findMany({ + where: { status: 'succeeded', createdAt: { gte: start30 } }, + select: { amount: true }, + }), + ]); + + const mrr = mrrPayments.reduce((s, p) => s + p.amount, 0); + + return { + activeDoctor, + activeOrg, + pastDue, + canceled, + mrr, + }; + } + + async syncFromStripe(subscriptionId: string) { + const sub = await this.prisma.subscription.findFirst({ + where: { stripeSubscriptionId: subscriptionId }, + include: { user: { select: { id: true, email: true, username: true } } }, + }); + if (!sub) throw new NotFoundException('Subscription not found'); + + const stripeSub = await this.stripeService.retrieveSubscription(subscriptionId); + const item = stripeSub.items.data[0]; + const periodEnd = item?.current_period_end; + + await this.prisma.subscription.update({ + where: { id: sub.id }, + data: { + status: stripeSub.status as SubscriptionStatus, + cancelAtPeriodEnd: Boolean(stripeSub.cancel_at_period_end), + ...(periodEnd ? { currentPeriodEnd: new Date(periodEnd * 1000) } : {}), + }, + }); + + await this.auditLog.logAsSuperAdmin({ + action: 'admin.subscription.synced', + category: 'api', + target: `${sub.user.username} · ${stripeSub.id}`, + targetId: sub.id, + targetUserId: sub.user.id, + severity: 'info', + }); + + return { success: true, status: stripeSub.status }; + } + + async cancel(subscriptionId: string) { + const sub = await this.prisma.subscription.findFirst({ + where: { stripeSubscriptionId: subscriptionId }, + include: { user: { select: { id: true, email: true, username: true } } }, + }); + if (!sub) throw new NotFoundException('Subscription not found'); + + await this.stripeService.cancelSubscription(sub.stripeSubscriptionId); + + await this.prisma.subscription.update({ + where: { id: sub.id }, + data: { cancelAtPeriodEnd: true }, + }); + + await this.auditLog.logAsSuperAdmin({ + action: 'admin.subscription.canceled', + category: 'api', + target: `${sub.user.username} · ${sub.stripeSubscriptionId}`, + targetId: sub.id, + targetUserId: sub.user.id, + severity: 'warning', + }); + + return { success: true }; + } + + async recentPayments(limit = 20) { + const take = Math.min(100, Math.max(1, Number(limit) || 20)); + return this.prisma.payment.findMany({ + orderBy: { createdAt: 'desc' }, + take, + include: { + user: { + select: { id: true, username: true, email: true }, + }, + }, + }); + } +} diff --git a/server/src/SuperAdmin/services/overview.service.ts b/server/src/SuperAdmin/services/overview.service.ts new file mode 100644 index 0000000..441da4c --- /dev/null +++ b/server/src/SuperAdmin/services/overview.service.ts @@ -0,0 +1,153 @@ +import { Injectable } from '@nestjs/common'; +import { PrismaService } from '../../../prisma/prisma.service'; + +type CacheEntry = { value: T; expiresAt: number }; + +@Injectable() +export class OverviewService { + private cache = new Map>(); + private readonly TTL_MS = 60_000; + + constructor(private prisma: PrismaService) {} + + private async cached(key: string, loader: () => Promise): Promise { + const hit = this.cache.get(key); + if (hit && hit.expiresAt > Date.now()) return hit.value as T; + const value = await loader(); + this.cache.set(key, { value, expiresAt: Date.now() + this.TTL_MS }); + return value; + } + + async getOverview() { + return this.cached('overview', async () => { + const now = new Date(); + const day = 24 * 60 * 60 * 1000; + const startOfToday = new Date(now); + startOfToday.setUTCHours(0, 0, 0, 0); + const sevenDaysAgo = new Date(now.getTime() - 7 * day); + const fourteenDaysAgo = new Date(now.getTime() - 14 * day); + const thirtyDaysAgo = new Date(now.getTime() - 30 * day); + + const [ + totalUsers, + usersLast7, + usersPrev7, + activeDoctor, + activeOrg, + scansToday, + scans7d, + scans30d, + reportsToday, + reports7d, + reports30d, + openTickets, + signups30dRaw, + scansPerDay30dRaw, + planFree, + planDoctor, + planOrg, + paidPayments, + recentSignups, + recentTickets, + ] = await this.prisma.$transaction([ + this.prisma.user.count(), + this.prisma.user.count({ where: { createdAt: { gte: sevenDaysAgo } } }), + this.prisma.user.count({ + where: { createdAt: { gte: fourteenDaysAgo, lt: sevenDaysAgo } }, + }), + this.prisma.subscription.count({ + where: { status: 'active', user: { plan: 'DOCTOR' } }, + }), + this.prisma.subscription.count({ + where: { status: 'active', user: { plan: 'ORGANIZATION' } }, + }), + this.prisma.scan.count({ where: { createdAt: { gte: startOfToday } } }), + this.prisma.scan.count({ where: { createdAt: { gte: sevenDaysAgo } } }), + this.prisma.scan.count({ where: { createdAt: { gte: thirtyDaysAgo } } }), + this.prisma.report.count({ where: { createdAt: { gte: startOfToday } } }), + this.prisma.report.count({ where: { createdAt: { gte: sevenDaysAgo } } }), + this.prisma.report.count({ where: { createdAt: { gte: thirtyDaysAgo } } }), + this.prisma.ticket.count({ where: { status: 'OPEN' } }), + this.prisma.user.findMany({ + where: { createdAt: { gte: thirtyDaysAgo } }, + select: { createdAt: true }, + }), + this.prisma.scan.findMany({ + where: { createdAt: { gte: thirtyDaysAgo } }, + select: { createdAt: true }, + }), + this.prisma.user.count({ where: { plan: 'FREE' } }), + this.prisma.user.count({ where: { plan: 'DOCTOR' } }), + this.prisma.user.count({ where: { plan: 'ORGANIZATION' } }), + this.prisma.payment.findMany({ + where: { + status: 'succeeded', + createdAt: { gte: thirtyDaysAgo }, + }, + select: { amount: true }, + }), + this.prisma.user.findMany({ + orderBy: { createdAt: 'desc' }, + take: 10, + select: { + id: true, + username: true, + email: true, + plan: true, + role: true, + profile_image_url: true, + createdAt: true, + }, + }), + this.prisma.ticket.findMany({ + orderBy: { createdAt: 'desc' }, + take: 10, + include: { + submittedBy: { + select: { id: true, username: true, email: true }, + }, + }, + }), + ]); + + const usersDelta7d = usersPrev7 === 0 + ? (usersLast7 > 0 ? 100 : 0) + : Math.round(((usersLast7 - usersPrev7) / usersPrev7) * 100); + + const mrr = paidPayments.reduce((sum, p) => sum + p.amount, 0); + + const signupsByDay = this.bucketByDay(signups30dRaw.map((u) => u.createdAt), 30); + const scansByDay = this.bucketByDay(scansPerDay30dRaw.map((s) => s.createdAt), 30); + + return { + totalUsers, + usersDelta7d, + activeSubscriptions: { doctor: activeDoctor, org: activeOrg }, + scansProcessed: { today: scansToday, last7d: scans7d, last30d: scans30d }, + reportsGenerated: { today: reportsToday, last7d: reports7d, last30d: reports30d }, + mrr, + openTicketsCount: openTickets, + signups30d: signupsByDay, + scansPerDay30d: scansByDay, + planDistribution: { free: planFree, doctor: planDoctor, org: planOrg }, + recentSignups, + recentTickets, + }; + }); + } + + private bucketByDay(dates: Date[], days: number): { date: string; count: number }[] { + const buckets = new Map(); + const today = new Date(); + today.setUTCHours(0, 0, 0, 0); + for (let i = days - 1; i >= 0; i--) { + const d = new Date(today.getTime() - i * 24 * 60 * 60 * 1000); + buckets.set(d.toISOString().slice(0, 10), 0); + } + for (const date of dates) { + const key = date.toISOString().slice(0, 10); + if (buckets.has(key)) buckets.set(key, (buckets.get(key) ?? 0) + 1); + } + return Array.from(buckets.entries()).map(([date, count]) => ({ date, count })); + } +} diff --git a/server/src/SuperAdmin/services/tickets.service.ts b/server/src/SuperAdmin/services/tickets.service.ts new file mode 100644 index 0000000..080c678 --- /dev/null +++ b/server/src/SuperAdmin/services/tickets.service.ts @@ -0,0 +1,398 @@ +import { + Injectable, + NotFoundException, + BadRequestException, +} from '@nestjs/common'; +import { InjectQueue } from '@nestjs/bullmq'; +import type { Queue } from 'bullmq'; +import { EventEmitter2 } from '@nestjs/event-emitter'; +import { randomBytes } from 'crypto'; +import { PrismaService } from '../../../prisma/prisma.service'; +import { AuditLogService } from '../../Organization/audit-log.service'; +import { REPORT_QUEUE, ReportJobData } from '../../Report/report.processor'; +import { ListTicketsDto } from '../dto/ticket.dto'; +import { TicketStatus, TicketType, TicketPriority } from '../../../prisma/generated/client/enums'; + +@Injectable() +export class TicketsAdminService { + constructor( + private prisma: PrismaService, + private auditLog: AuditLogService, + @InjectQueue(REPORT_QUEUE) private reportQueue: Queue, + private eventEmitter: EventEmitter2, + ) {} + + private generateCode() { + return `TKT-${randomBytes(3).toString('hex').toUpperCase()}`; + } + + async list(filters: ListTicketsDto) { + const page = Math.max(1, Number(filters.page) || 1); + const pageSize = Math.min(100, Math.max(1, Number(filters.pageSize) || 25)); + + const where: any = {}; + if (filters.status) where.status = filters.status; + if (filters.type) where.type = filters.type; + if (filters.priority) where.priority = filters.priority; + const q = filters.q?.trim(); + if (q) { + where.OR = [ + { code: { contains: q, mode: 'insensitive' } }, + { reason: { contains: q, mode: 'insensitive' } }, + { submittedBy: { email: { contains: q, mode: 'insensitive' } } }, + { submittedBy: { username: { contains: q, mode: 'insensitive' } } }, + ]; + } + + const [items, total] = await this.prisma.$transaction([ + this.prisma.ticket.findMany({ + where, + orderBy: [{ status: 'asc' }, { createdAt: 'desc' }], + skip: (page - 1) * pageSize, + take: pageSize, + include: { + submittedBy: { + select: { id: true, username: true, email: true, profile_image_url: true }, + }, + assignedTo: { + select: { id: true, username: true, email: true }, + }, + scan: { select: { id: true, scan_code: true, class: true } }, + report: { select: { id: true, code: true } }, + }, + }), + this.prisma.ticket.count({ where }), + ]); + + return { items, total, page, pageSize }; + } + + async detail(code: string) { + const ticket = await this.prisma.ticket.findUnique({ + where: { code }, + include: { + submittedBy: { + select: { id: true, username: true, email: true, profile_image_url: true, plan: true }, + }, + assignedTo: { + select: { id: true, username: true, email: true }, + }, + scan: { + include: { + patient: { select: { id: true, full_name: true } }, + scanImage: true, + report: { select: { id: true, code: true } }, + }, + }, + report: { + include: { + scan: { + include: { + patient: { select: { id: true, full_name: true } }, + }, + }, + }, + }, + reanalysisScan: { select: { id: true, scan_code: true, class: true, confidence_score: true } }, + reanalysisReport: { select: { id: true, code: true } }, + }, + }); + if (!ticket) throw new NotFoundException('Ticket not found'); + return ticket; + } + + async assign(code: string, assignedToId: string) { + const ticket = await this.prisma.ticket.findUnique({ where: { code } }); + if (!ticket) throw new NotFoundException('Ticket not found'); + + const assignee = await this.prisma.user.findUnique({ + where: { id: assignedToId }, + select: { id: true, username: true, email: true, role: true }, + }); + if (!assignee || assignee.role !== 'SUPER_ADMIN') { + throw new BadRequestException('Assignee must be a super admin'); + } + + const updated = await this.prisma.ticket.update({ + where: { id: ticket.id }, + data: { + assignedToId, + status: ticket.status === 'OPEN' ? 'IN_PROGRESS' : ticket.status, + }, + }); + + await this.auditLog.logAsSuperAdmin({ + action: 'admin.ticket.assigned', + category: 'reports', + target: `${ticket.code} → ${assignee.username}`, + targetId: ticket.id, + targetUserId: ticket.submittedById, + severity: 'info', + }); + + return updated; + } + + async reanalyze(code: string) { + const ticket = await this.prisma.ticket.findUnique({ + where: { code }, + include: { + scan: { include: { scanImage: true } }, + submittedBy: { select: { id: true, username: true, email: true } }, + }, + }); + if (!ticket) throw new NotFoundException('Ticket not found'); + if (ticket.type !== TicketType.RE_ANALYSIS) { + throw new BadRequestException('Ticket is not a re-analysis request'); + } + if (!ticket.scan || !ticket.scan.scanImage) { + throw new BadRequestException('Original scan or image missing'); + } + + // Fetch the original image from storage and re-run the model. + const imageUrl = ticket.scan.scanImage.url; + const imgResp = await fetch(imageUrl); + if (!imgResp.ok) { + throw new BadRequestException('Failed to fetch original scan image'); + } + const imgBlob = await imgResp.blob(); + + const formData = new FormData(); + formData.append( + 'file', + imgBlob, + ticket.scan.scanImage.name || 'scan.png', + ); + + const startTime = Date.now(); + const response = await fetch(`${process.env.ML_MODEL_URL}/predict`, { + method: 'POST', + body: formData, + headers: { + Authorization: `Bearer ${process.env.ML_MODEL_API_KEY}`, + }, + }); + const processingTime = (Date.now() - startTime) / 1000; + const result = await response.json(); + if (!result.success) { + throw new BadRequestException(result.message || 'Re-analysis failed'); + } + + const scanCode = `scan-${randomBytes(4).toString('hex')}`; + const newScan = await this.prisma.scan.create({ + data: { + scan_code: scanCode, + uploadedById: ticket.scan.uploadedById, + class: result.class, + confidence_score: result.confidence, + all_scores: result.all_scores, + processing: processingTime, + status: 'DONE', + name: ticket.scan.name ? `${ticket.scan.name} (re-analysis)` : null, + notes: `Re-analysis from ticket ${ticket.code}`, + patientId: ticket.scan.patientId, + orgId: ticket.scan.orgId, + }, + }); + + await this.prisma.scanImage.create({ + data: { + scanId: newScan.id, + url: ticket.scan.scanImage.url, + size: ticket.scan.scanImage.size, + resolution: ticket.scan.scanImage.resolution, + format: ticket.scan.scanImage.format, + name: ticket.scan.scanImage.name, + }, + }); + + const updated = await this.prisma.ticket.update({ + where: { id: ticket.id }, + data: { + reanalysisScanId: newScan.id, + status: 'IN_PROGRESS', + }, + }); + + await this.auditLog.logAsSuperAdmin({ + action: 'admin.ticket.reanalyzed', + category: 'scans', + target: `${ticket.code} → ${newScan.scan_code}`, + targetId: ticket.id, + targetUserId: ticket.submittedById, + severity: 'info', + }); + + return updated; + } + + async regenerate(code: string) { + const ticket = await this.prisma.ticket.findUnique({ + where: { code }, + include: { + report: { include: { scan: true } }, + }, + }); + if (!ticket) throw new NotFoundException('Ticket not found'); + if (ticket.type !== TicketType.RE_REPORT) { + throw new BadRequestException('Ticket is not a re-report request'); + } + if (!ticket.report) throw new BadRequestException('Original report missing'); + + const jobData: ReportJobData = { + scan_id: ticket.report.scanId, + userId: ticket.report.scan.uploadedById, + ip: null, + userAgent: null, + }; + const job = await this.reportQueue.add('generate', jobData, { + attempts: 3, + backoff: { type: 'exponential', delay: 5000 }, + }); + + const updated = await this.prisma.ticket.update({ + where: { id: ticket.id }, + data: { status: 'IN_PROGRESS' }, + }); + + await this.auditLog.logAsSuperAdmin({ + action: 'admin.ticket.regenerated', + category: 'reports', + target: `${ticket.code} → ${ticket.report.code}`, + targetId: ticket.id, + targetUserId: ticket.submittedById, + severity: 'info', + }); + + return { ...updated, jobId: job.id }; + } + + async resolve(code: string, resolutionNote: string) { + const ticket = await this.prisma.ticket.findUnique({ where: { code } }); + if (!ticket) throw new NotFoundException('Ticket not found'); + + const updated = await this.prisma.ticket.update({ + where: { id: ticket.id }, + data: { + status: 'RESOLVED', + resolutionNote, + resolvedAt: new Date(), + }, + }); + + await this.auditLog.logAsSuperAdmin({ + action: 'admin.ticket.resolved', + category: 'reports', + target: ticket.code, + targetId: ticket.id, + targetUserId: ticket.submittedById, + severity: 'success', + }); + + this.eventEmitter.emit('notification.send', { + userId: ticket.submittedById, + type: 'TICKET_RESOLVED', + payload: { + ticketCode: ticket.code, + ticketType: ticket.type, + resolutionNote, + }, + }); + + return updated; + } + + async dismiss(code: string, resolutionNote?: string) { + const ticket = await this.prisma.ticket.findUnique({ where: { code } }); + if (!ticket) throw new NotFoundException('Ticket not found'); + + const updated = await this.prisma.ticket.update({ + where: { id: ticket.id }, + data: { + status: 'DISMISSED', + resolutionNote: resolutionNote ?? null, + resolvedAt: new Date(), + }, + }); + + await this.auditLog.logAsSuperAdmin({ + action: 'admin.ticket.dismissed', + category: 'reports', + target: ticket.code, + targetId: ticket.id, + targetUserId: ticket.submittedById, + severity: 'warning', + }); + + this.eventEmitter.emit('notification.send', { + userId: ticket.submittedById, + type: 'TICKET_DISMISSED', + payload: { + ticketCode: ticket.code, + ticketType: ticket.type, + resolutionNote: resolutionNote ?? null, + }, + }); + + return updated; + } + + // User-facing flag helpers (called from ScanResult / Report modules) + async createFromScan(params: { + userId: string; + scanResultId: string; + type: TicketType; + reason: string; + priority?: TicketPriority; + }) { + const scan = await this.prisma.scan.findUnique({ + where: { id: params.scanResultId }, + include: { report: true }, + }); + if (!scan) throw new NotFoundException('Scan not found'); + + const code = this.generateCode(); + return this.prisma.ticket.create({ + data: { + code, + type: params.type, + priority: params.priority ?? 'MEDIUM', + reason: params.reason, + scanId: scan.id, + reportId: scan.report?.id ?? null, + submittedById: params.userId, + status: 'OPEN' as TicketStatus, + }, + select: { code: true, id: true, status: true }, + }); + } + + async createFromReport(params: { + userId: string; + reportCode: string; + type: TicketType; + reason: string; + priority?: TicketPriority; + }) { + const report = await this.prisma.report.findUnique({ + where: { code: params.reportCode }, + include: { scan: true }, + }); + if (!report) throw new NotFoundException('Report not found'); + + const code = this.generateCode(); + return this.prisma.ticket.create({ + data: { + code, + type: params.type, + priority: params.priority ?? 'MEDIUM', + reason: params.reason, + scanId: report.scanId, + reportId: report.id, + submittedById: params.userId, + status: 'OPEN' as TicketStatus, + }, + select: { code: true, id: true, status: true }, + }); + } +} diff --git a/server/src/SuperAdmin/services/users.service.ts b/server/src/SuperAdmin/services/users.service.ts new file mode 100644 index 0000000..df6b43f --- /dev/null +++ b/server/src/SuperAdmin/services/users.service.ts @@ -0,0 +1,297 @@ +import { Injectable, NotFoundException, BadRequestException } from '@nestjs/common'; +import { randomBytes } from 'crypto'; +import { PrismaService } from '../../../prisma/prisma.service'; +import { AuditLogService } from '../../Organization/audit-log.service'; +import { ListUsersDto } from '../dto/list-users.dto'; +import { Role } from '../../../prisma/generated/client/enums'; + +@Injectable() +export class UsersAdminService { + constructor( + private prisma: PrismaService, + private auditLog: AuditLogService, + ) {} + + async list(filters: ListUsersDto) { + const page = Math.max(1, Number(filters.page) || 1); + const pageSize = Math.min(100, Math.max(1, Number(filters.pageSize) || 25)); + + const where: any = {}; + if (filters.plan) where.plan = filters.plan; + if (filters.role) where.role = filters.role; + if (filters.status === 'active') where.is_active = true; + if (filters.status === 'inactive') where.is_active = false; + if (filters.hasOrg === 'true') { + where.OR = [{ ownedOrg: { isNot: null } }, { orgMember: { isNot: null } }]; + } + if (filters.hasOrg === 'false') { + where.AND = [{ ownedOrg: null }, { orgMember: null }]; + } + const q = filters.q?.trim(); + if (q) { + const search = [ + { email: { contains: q, mode: 'insensitive' as const } }, + { username: { contains: q, mode: 'insensitive' as const } }, + ]; + where.OR = where.OR ? [...where.OR, ...search] : search; + } + + const [items, total] = await this.prisma.$transaction([ + this.prisma.user.findMany({ + where, + orderBy: { createdAt: 'desc' }, + skip: (page - 1) * pageSize, + take: pageSize, + select: { + id: true, + username: true, + email: true, + role: true, + plan: true, + is_active: true, + profile_image_url: true, + total_scans: true, + total_reports: true, + createdAt: true, + ownedOrg: { select: { id: true, name: true } }, + orgMember: { select: { id: true, orgId: true } }, + }, + }), + this.prisma.user.count({ where }), + ]); + + return { items, total, page, pageSize }; + } + + async getProfile(id: string) { + const user = await this.prisma.user.findUnique({ + where: { id }, + select: { + id: true, + username: true, + email: true, + role: true, + plan: true, + is_active: true, + profile_image_url: true, + total_scans: true, + total_reports: true, + twoFactorEnabled: true, + createdAt: true, + updatedAt: true, + ownedOrg: { select: { id: true, name: true, createdAt: true } }, + orgMember: { + select: { + id: true, + isActive: true, + org: { select: { id: true, name: true } }, + }, + }, + subscription: { + select: { + status: true, + currentPeriodEnd: true, + cancelAtPeriodEnd: true, + stripeSubscriptionId: true, + }, + }, + }, + }); + if (!user) throw new NotFoundException('User not found'); + return user; + } + + async getScans(userId: string, page = 1, pageSize = 20) { + const p = Math.max(1, Number(page) || 1); + const ps = Math.min(100, Math.max(1, Number(pageSize) || 20)); + const where = { uploadedById: userId }; + const [items, total] = await this.prisma.$transaction([ + this.prisma.scan.findMany({ + where, + orderBy: { createdAt: 'desc' }, + skip: (p - 1) * ps, + take: ps, + include: { + patient: { select: { id: true, full_name: true } }, + scanImage: { select: { url: true } }, + report: { select: { id: true, code: true } }, + }, + }), + this.prisma.scan.count({ where }), + ]); + return { items, total, page: p, pageSize: ps }; + } + + async getReports(userId: string, page = 1, pageSize = 20) { + const p = Math.max(1, Number(page) || 1); + const ps = Math.min(100, Math.max(1, Number(pageSize) || 20)); + const where = { scan: { uploadedById: userId } }; + const [items, total] = await this.prisma.$transaction([ + this.prisma.report.findMany({ + where, + orderBy: { createdAt: 'desc' }, + skip: (p - 1) * ps, + take: ps, + include: { + scan: { + select: { + id: true, + scan_code: true, + class: true, + patient: { select: { id: true, full_name: true } }, + }, + }, + }, + }), + this.prisma.report.count({ where }), + ]); + return { items, total, page: p, pageSize: ps }; + } + + async getPatients(userId: string, page = 1, pageSize = 20) { + const p = Math.max(1, Number(page) || 1); + const ps = Math.min(100, Math.max(1, Number(pageSize) || 20)); + const where = { createdById: userId }; + const [items, total] = await this.prisma.$transaction([ + this.prisma.patient.findMany({ + where, + orderBy: { createdAt: 'desc' }, + skip: (p - 1) * ps, + take: ps, + include: { + _count: { select: { scans: true } }, + }, + }), + this.prisma.patient.count({ where }), + ]); + return { items, total, page: p, pageSize: ps }; + } + + async getOrganization(userId: string) { + const org = await this.prisma.organization.findUnique({ + where: { ownerId: userId }, + include: { + members: { + include: { + user: { + select: { + id: true, + username: true, + email: true, + profile_image_url: true, + is_active: true, + }, + }, + }, + }, + patients: { + orderBy: { createdAt: 'desc' }, + include: { _count: { select: { scans: true } } }, + }, + apiKeys: { + orderBy: { createdAt: 'desc' }, + }, + }, + }); + if (!org) return null; + return org; + } + + async setStatus(targetUserId: string, isActive: boolean) { + const target = await this.prisma.user.findUnique({ + where: { id: targetUserId }, + select: { id: true, username: true, email: true, role: true, is_active: true }, + }); + if (!target) throw new NotFoundException('User not found'); + if (target.role === Role.SUPER_ADMIN) { + throw new BadRequestException('Cannot deactivate a super admin'); + } + + const updated = await this.prisma.user.update({ + where: { id: targetUserId }, + data: { is_active: isActive }, + select: { id: true, is_active: true }, + }); + + await this.auditLog.logAsSuperAdmin({ + action: isActive ? 'admin.user.activated' : 'admin.user.deactivated', + category: 'members', + target: `${target.username} · ${target.email}`, + targetId: target.id, + targetUserId: target.id, + severity: isActive ? 'info' : 'warning', + }); + + return updated; + } + + async forceReset(targetUserId: string) { + const target = await this.prisma.user.findUnique({ + where: { id: targetUserId }, + select: { id: true, username: true, email: true, password: true }, + }); + if (!target) throw new NotFoundException('User not found'); + if (!target.password) { + throw new BadRequestException('User signs in via Google — password reset not applicable'); + } + + const token = randomBytes(32).toString('hex'); + const expires = new Date(Date.now() + 3600_000); + + await this.prisma.user.update({ + where: { id: target.id }, + data: { reset_password_token: token, reset_token_expires: expires }, + }); + + await this.auditLog.logAsSuperAdmin({ + action: 'admin.user.force_reset', + category: 'members', + target: `${target.username} · ${target.email}`, + targetId: target.id, + targetUserId: target.id, + severity: 'warning', + }); + + return { success: true, resetToken: token, expiresAt: expires }; + } + + async softDelete(targetUserId: string) { + const target = await this.prisma.user.findUnique({ + where: { id: targetUserId }, + select: { id: true, username: true, email: true, role: true }, + }); + if (!target) throw new NotFoundException('User not found'); + if (target.role === Role.SUPER_ADMIN) { + throw new BadRequestException('Cannot delete a super admin'); + } + + // Soft delete: deactivate + scramble email/username to free unique slots. + const stamp = Date.now(); + const suffix = `_deleted_${stamp}`; + await this.prisma.user.update({ + where: { id: target.id }, + data: { + is_active: false, + email: `${target.email}${suffix}`, + username: `${target.username}${suffix}`, + password: null, + googleId: null, + reset_password_token: null, + reset_token_expires: null, + twoFactorEnabled: false, + twoFactorSecret: null, + }, + }); + + await this.auditLog.logAsSuperAdmin({ + action: 'admin.user.deleted', + category: 'members', + target: `${target.username} · ${target.email}`, + targetId: target.id, + targetUserId: target.id, + severity: 'danger', + }); + + return { success: true }; + } +} diff --git a/server/src/SuperAdmin/super-admin.module.ts b/server/src/SuperAdmin/super-admin.module.ts new file mode 100644 index 0000000..e21e723 --- /dev/null +++ b/server/src/SuperAdmin/super-admin.module.ts @@ -0,0 +1,39 @@ +import { Module } from '@nestjs/common'; +import { BullModule } from '@nestjs/bullmq'; +import { PrismaService } from '../../prisma/prisma.service'; +import { SuperAdminGuard } from './guards/super-admin.guard'; +import { AuditLogService } from '../Organization/audit-log.service'; + +import { OverviewController } from './controllers/overview.controller'; +import { OverviewService } from './services/overview.service'; +import { UsersAdminController } from './controllers/users.controller'; +import { UsersAdminService } from './services/users.service'; +import { BillingAdminController } from './controllers/billing.controller'; +import { BillingAdminService } from './services/billing.service'; +import { AuditAdminController } from './controllers/audit.controller'; +import { TicketsAdminController } from './controllers/tickets.controller'; +import { TicketsAdminService } from './services/tickets.service'; +import { StripeService } from '../Stripe/stripe.service'; +import { REPORT_QUEUE } from '../Report/report.processor'; + +@Module({ + imports: [BullModule.registerQueue({ name: REPORT_QUEUE })], + controllers: [ + OverviewController, + UsersAdminController, + BillingAdminController, + AuditAdminController, + TicketsAdminController, + ], + providers: [ + PrismaService, + SuperAdminGuard, + AuditLogService, + OverviewService, + UsersAdminService, + BillingAdminService, + TicketsAdminService, + StripeService, + ], +}) +export class SuperAdminModule {} diff --git a/server/src/app.module.ts b/server/src/app.module.ts index e885dce..7bc58c3 100644 --- a/server/src/app.module.ts +++ b/server/src/app.module.ts @@ -17,6 +17,7 @@ import { StripeModule } from './Stripe/stripe.module'; import { TasksModule } from './Tasks/tasks.module'; import { EventEmitterModule } from '@nestjs/event-emitter'; import { PublicApiModule } from './Public-API/public-api.module'; +import { SuperAdminModule } from './SuperAdmin/super-admin.module'; @Module({ imports: [ @@ -43,7 +44,8 @@ import { PublicApiModule } from './Public-API/public-api.module'; SettingsModule, StripeModule, TasksModule, - PublicApiModule + PublicApiModule, + SuperAdminModule, ], controllers: [], providers: [], From ec74d2d36169d4a548fa89148779dd578a052b9b Mon Sep 17 00:00:00 2001 From: elwessdev Date: Wed, 20 May 2026 21:14:19 +0100 Subject: [PATCH 15/30] refactor: simplify navigation and routing for super admin features --- client/src/features/auth/google-callback.tsx | 4 +--- client/src/features/auth/hooks.ts | 1 + client/src/features/auth/login.tsx | 4 ++-- client/src/features/auth/route.ts | 5 +---- client/src/features/landing/index.tsx | 10 ++++++++++ client/src/features/landing/route.tsx | 9 ++++++--- .../components/SuperAdminLayout.tsx | 14 +++++++------- client/src/features/superadmin/route.ts | 19 ++++++------------- .../src/features/superadmin/routes/index.tsx | 4 ++-- .../superadmin/routes/tickets-detail.tsx | 2 +- .../features/superadmin/routes/tickets.tsx | 2 +- client/src/router.ts | 2 -- 12 files changed, 38 insertions(+), 38 deletions(-) diff --git a/client/src/features/auth/google-callback.tsx b/client/src/features/auth/google-callback.tsx index 766a165..186e3fe 100644 --- a/client/src/features/auth/google-callback.tsx +++ b/client/src/features/auth/google-callback.tsx @@ -31,9 +31,7 @@ export const GoogleCallbackPage = () => { data.user, data.notificationSettings ); - navigate({ - to: data.user?.role === "SUPER_ADMIN" ? "/superadmin" : "/" - }); + navigate({ to: "/" }); }) .catch(() => navigate({ to: "/login" })); }, [navigate, setAuth, token]); diff --git a/client/src/features/auth/hooks.ts b/client/src/features/auth/hooks.ts index 2223306..99423b6 100644 --- a/client/src/features/auth/hooks.ts +++ b/client/src/features/auth/hooks.ts @@ -27,6 +27,7 @@ export const useLogout = () => useMutation({ }, onSettled: () => { queryClient.clear(); + window.location.reload(); }, }); diff --git a/client/src/features/auth/login.tsx b/client/src/features/auth/login.tsx index 3119b2f..ac3da9a 100644 --- a/client/src/features/auth/login.tsx +++ b/client/src/features/auth/login.tsx @@ -27,7 +27,7 @@ export const LoginPage = () => { return; } setAuth(data.accessToken, data.user, data.notificationSettings); - navigate({ to: data.user?.role === "SUPER_ADMIN" ? "/superadmin" : "/" }); + navigate({ to: "/" }); }, onError: error => { const e = error as { response?: { data?: { message?: string } } }; @@ -46,7 +46,7 @@ export const LoginPage = () => { onSuccess: data => { if (data?.twoFactorRequired) return; setAuth(data.accessToken, data.user, data.notificationSettings); - navigate({ to: data.user?.role === "SUPER_ADMIN" ? "/superadmin" : "/" }); + navigate({ to: "/" }); }, onError: error => { const e = error as { response?: { data?: { message?: string } } }; diff --git a/client/src/features/auth/route.ts b/client/src/features/auth/route.ts index 79b7589..f7afb15 100644 --- a/client/src/features/auth/route.ts +++ b/client/src/features/auth/route.ts @@ -7,10 +7,7 @@ import { ForgotPasswordPage } from "./forgot-password"; import { ResetPasswordPage } from "./reset-password"; import { GoogleCallbackPage } from "./google-callback"; -const homeForRole = () => { - const { user } = useAuthStore.getState(); - return user?.role === "SUPER_ADMIN" ? "/superadmin" : "/"; -}; +const homeForRole = () => "/"; // Register page route export const RegisterPageRoute = createRoute({ diff --git a/client/src/features/landing/index.tsx b/client/src/features/landing/index.tsx index 2c0455b..6ef8d8e 100644 --- a/client/src/features/landing/index.tsx +++ b/client/src/features/landing/index.tsx @@ -4,6 +4,8 @@ import { useAuthStore } from "../../store/auth.store"; import Logo from "../../components/logo"; import { MI } from "../../components/logo"; import { DashboardLayout } from "../dashboard/layout"; +import { SuperAdminLayout } from "../superadmin/components/SuperAdminLayout"; +import { OverviewPage } from "../superadmin/routes"; import { PLANS, type PlanFeature } from "../dashboard/Plans/helpers"; import { useState, useEffect, useRef } from "react"; @@ -898,6 +900,14 @@ const LandingPage = () => { export const IndexPage = () => { const accessToken = useAuthStore((state) => state.accessToken); + const role = useAuthStore((state) => state.user?.role); + if (accessToken && role === "SUPER_ADMIN") { + return ( + + + + ); + } if (accessToken) return ; return ; }; diff --git a/client/src/features/landing/route.tsx b/client/src/features/landing/route.tsx index c80d9eb..f058988 100644 --- a/client/src/features/landing/route.tsx +++ b/client/src/features/landing/route.tsx @@ -6,9 +6,12 @@ import { IndexPage } from "."; export const AppLayoutRoute = createRoute({ getParentRoute: () => rootRoute, id: "app-layout", - beforeLoad: () => { - if (useAuthStore.getState().user?.role === "SUPER_ADMIN") { - throw redirect({ to: "/superadmin" }); + beforeLoad: ({ location }) => { + if ( + useAuthStore.getState().user?.role === "SUPER_ADMIN" && + location.pathname !== "/" + ) { + throw redirect({ to: "/" }); } }, component: IndexPage diff --git a/client/src/features/superadmin/components/SuperAdminLayout.tsx b/client/src/features/superadmin/components/SuperAdminLayout.tsx index 917f4df..fb72838 100644 --- a/client/src/features/superadmin/components/SuperAdminLayout.tsx +++ b/client/src/features/superadmin/components/SuperAdminLayout.tsx @@ -13,14 +13,14 @@ import { useLogout } from "../../auth/hooks"; type NavItem = { to: string; label: string; Icon: React.ComponentType<{ size?: number; color?: string }>; exact?: boolean }; const NAV: NavItem[] = [ - { to: "/superadmin", label: "Overview", Icon: MdSpaceDashboard, exact: true }, - { to: "/superadmin/users", label: "Users", Icon: MdPeopleAlt }, - { to: "/superadmin/billing", label: "Billing", Icon: MdAttachMoney }, - { to: "/superadmin/audit-logs", label: "Audit Logs", Icon: MdReceiptLong }, - { to: "/superadmin/tickets", label: "Tickets", Icon: MdSupportAgent }, + { to: "/", label: "Overview", Icon: MdSpaceDashboard, exact: true }, + { to: "/users", label: "Users", Icon: MdPeopleAlt }, + { to: "/billing", label: "Billing", Icon: MdAttachMoney }, + { to: "/audit-logs", label: "Audit Logs", Icon: MdReceiptLong }, + { to: "/tickets", label: "Tickets", Icon: MdSupportAgent }, ]; -export const SuperAdminLayout = () => { +export const SuperAdminLayout = ({ children }: { children?: React.ReactNode }) => { const currentPath = useRouterState({ select: (s) => s.location.pathname }); const user = useAuthStore((s) => s.user); const clear = useAuthStore((s) => s.clear); @@ -201,7 +201,7 @@ export const SuperAdminLayout = () => {
- + {children ?? }
diff --git a/client/src/features/superadmin/route.ts b/client/src/features/superadmin/route.ts index bedd9a2..6ece2b0 100644 --- a/client/src/features/superadmin/route.ts +++ b/client/src/features/superadmin/route.ts @@ -2,7 +2,6 @@ import { createRoute, redirect } from "@tanstack/react-router"; import { rootRoute } from "../../rootRoute"; import { useAuthStore } from "../../store/auth.store"; import { SuperAdminLayout } from "./components/SuperAdminLayout"; -import { OverviewPage } from "./routes"; import { UsersPage } from "./routes/users"; import { BillingPage } from "./routes/billing"; import { AuditLogsPage } from "./routes/audit-logs"; @@ -17,43 +16,37 @@ const requireSuperAdmin = () => { export const SuperAdminRoute = createRoute({ getParentRoute: () => rootRoute, - path: "superadmin", + id: "superadmin-layout", beforeLoad: requireSuperAdmin, component: SuperAdminLayout, }); -export const SuperAdminOverviewRoute = createRoute({ - getParentRoute: () => SuperAdminRoute, - path: "/", - component: OverviewPage, -}); - export const SuperAdminUsersRoute = createRoute({ getParentRoute: () => SuperAdminRoute, - path: "users", + path: "/users", component: UsersPage, }); export const SuperAdminBillingRoute = createRoute({ getParentRoute: () => SuperAdminRoute, - path: "billing", + path: "/billing", component: BillingPage, }); export const SuperAdminAuditLogsRoute = createRoute({ getParentRoute: () => SuperAdminRoute, - path: "audit-logs", + path: "/audit-logs", component: AuditLogsPage, }); export const SuperAdminTicketsRoute = createRoute({ getParentRoute: () => SuperAdminRoute, - path: "tickets", + path: "/tickets", component: TicketsPage, }); export const SuperAdminTicketDetailRoute = createRoute({ getParentRoute: () => SuperAdminRoute, - path: "tickets/$code", + path: "/tickets/$code", component: TicketDetailPage, }); diff --git a/client/src/features/superadmin/routes/index.tsx b/client/src/features/superadmin/routes/index.tsx index ef58996..f754f5e 100644 --- a/client/src/features/superadmin/routes/index.tsx +++ b/client/src/features/superadmin/routes/index.tsx @@ -402,7 +402,7 @@ export const OverviewPage = () => { } extra={ {
{data.recentTickets.map((t, i) => ( s === "OPEN" ? "red" : s === "IN_PROGRESS" ? "orange" : s === "RESOLVED" ? "green" : "default"; export const TicketDetailPage = () => { - const { code } = useParams({ from: "/superadmin/tickets/$code" }); + const { code } = useParams({ from: "/tickets/$code" }); const qc = useQueryClient(); const [resolutionNote, setResolutionNote] = useState(""); diff --git a/client/src/features/superadmin/routes/tickets.tsx b/client/src/features/superadmin/routes/tickets.tsx index ef1ead9..d7189b6 100644 --- a/client/src/features/superadmin/routes/tickets.tsx +++ b/client/src/features/superadmin/routes/tickets.tsx @@ -84,7 +84,7 @@ export const TicketsPage = () => { size="middle" onRow={(record) => ({ onClick: () => - navigate({ to: "/superadmin/tickets/$code", params: { code: record.code } }), + navigate({ to: "/tickets/$code", params: { code: record.code } }), style: { cursor: "pointer" }, })} pagination={{ diff --git a/client/src/router.ts b/client/src/router.ts index 1acd4d9..dcab9fa 100644 --- a/client/src/router.ts +++ b/client/src/router.ts @@ -27,7 +27,6 @@ import { } from "./features/dashboard/Organization/routes"; import { SuperAdminRoute, - SuperAdminOverviewRoute, SuperAdminUsersRoute, SuperAdminBillingRoute, SuperAdminAuditLogsRoute, @@ -64,7 +63,6 @@ const routeTree = rootRoute.addChildren([ ResetPasswordPageRoute, GoogleCallbackRoute, SuperAdminRoute.addChildren([ - SuperAdminOverviewRoute, SuperAdminUsersRoute, SuperAdminBillingRoute, SuperAdminAuditLogsRoute, From 070562bf37889cea52571b3fbeeae1f62d0600e5 Mon Sep 17 00:00:00 2001 From: elwessdev Date: Thu, 21 May 2026 09:03:30 +0100 Subject: [PATCH 16/30] refactor: update ticket detail page to use SuperAdminTicketDetailRoute for parameter handling and improve text overflow styling --- client/src/features/superadmin/routes/tickets-detail.tsx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/client/src/features/superadmin/routes/tickets-detail.tsx b/client/src/features/superadmin/routes/tickets-detail.tsx index c21b5ba..b87e6c3 100644 --- a/client/src/features/superadmin/routes/tickets-detail.tsx +++ b/client/src/features/superadmin/routes/tickets-detail.tsx @@ -1,5 +1,5 @@ import { useState } from "react"; -import { useParams } from "@tanstack/react-router"; +import { SuperAdminTicketDetailRoute } from "../route"; import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { Card, @@ -33,7 +33,7 @@ const statusColor = (s: string) => s === "OPEN" ? "red" : s === "IN_PROGRESS" ? "orange" : s === "RESOLVED" ? "green" : "default"; export const TicketDetailPage = () => { - const { code } = useParams({ from: "/tickets/$code" }); + const { code } = SuperAdminTicketDetailRoute.useParams(); const qc = useQueryClient(); const [resolutionNote, setResolutionNote] = useState(""); @@ -202,7 +202,10 @@ export const TicketDetailPage = () => { style={{ fontSize: 11, maxHeight: 280, - overflow: "auto", + overflowY: "auto", + overflowX: "hidden", + whiteSpace: "pre-wrap", + wordBreak: "break-word", background: "#f8fafc", padding: 10, borderRadius: 6, From 4a4c541518fc5c7b2cc2bd02de15a41d2ef2347e Mon Sep 17 00:00:00 2001 From: elwessdev Date: Tue, 9 Jun 2026 23:30:25 +0100 Subject: [PATCH 17/30] feat: implement command palette for quick navigation and search functionality --- .../src/features/dashboard/History/index.tsx | 21 - .../dashboard/components/CommandPalette.tsx | 370 ++++++++++++++++++ client/src/features/dashboard/layout.tsx | 48 ++- client/src/router.ts | 2 - docker-compose.yml | 2 +- 5 files changed, 402 insertions(+), 41 deletions(-) delete mode 100644 client/src/features/dashboard/History/index.tsx create mode 100644 client/src/features/dashboard/components/CommandPalette.tsx diff --git a/client/src/features/dashboard/History/index.tsx b/client/src/features/dashboard/History/index.tsx deleted file mode 100644 index c2ded9d..0000000 --- a/client/src/features/dashboard/History/index.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { createRoute, redirect } from "@tanstack/react-router"; -import { useAuthStore } from "../../../store/auth.store"; -import { AppLayoutRoute } from "../../landing/route"; - -const HistoryPage = () => { - return ( -
-

History

-

This is where the history of scans and reports will be displayed.

-
- ); -} - -export const HistoryPageRoute = createRoute({ - getParentRoute: () => AppLayoutRoute, - path: "history", - beforeLoad: () => { - if (!useAuthStore.getState().accessToken) throw redirect({ to: "/login" }); - }, - component: HistoryPage, -}); \ No newline at end of file diff --git a/client/src/features/dashboard/components/CommandPalette.tsx b/client/src/features/dashboard/components/CommandPalette.tsx new file mode 100644 index 0000000..af18154 --- /dev/null +++ b/client/src/features/dashboard/components/CommandPalette.tsx @@ -0,0 +1,370 @@ +import { useEffect, useMemo, useRef, useState } from "react"; +import { useNavigate } from "@tanstack/react-router"; +import { + MdSearch, + MdDashboard, + MdCloudUpload, + MdCheckCircle, + MdDescription, + MdPeople, + MdSettings, + MdHelpOutline, + MdApartment, + MdInsertDriveFile, + MdPerson, + MdImage, + MdArrowForward, +} from "react-icons/md"; +import { queryClient } from "../../../main"; +import { useAuthStore } from "../../../store/auth.store"; +import type { Patient } from "../Patients/types"; +import type { ApiScan } from "../ScanResults/types"; +import type { Report } from "../Reports/types"; + +type ResultKind = "page" | "patient" | "scan" | "report"; +type Result = { + kind: ResultKind; + id: string; + title: string; + subtitle?: string; + Icon: React.ElementType; + onSelect: () => void; +}; + +const PAGES: { label: string; path: string; Icon: React.ElementType; plans?: string[] }[] = [ + { label: "Dashboard", path: "/", Icon: MdDashboard }, + { label: "Upload MRI Scan", path: "/upload", Icon: MdCloudUpload }, + { label: "Scan Results", path: "/results", Icon: MdCheckCircle }, + { label: "Reports", path: "/reports", Icon: MdDescription }, + { label: "Patients", path: "/patients", Icon: MdPeople, plans: ["DOCTOR", "ORGANIZATION"] }, + { label: "Members", path: "/organization/members", Icon: MdApartment, plans: ["ORGANIZATION"] }, + { label: "API Integration", path: "/organization/api-integration", Icon: MdDescription, plans: ["ORGANIZATION"] }, + { label: "Audit Logs", path: "/organization/audit-logs", Icon: MdHelpOutline, plans: ["ORGANIZATION"] }, + { label: "Settings", path: "/settings", Icon: MdSettings }, + { label: "Plans", path: "/plans", Icon: MdPeople }, + { label: "Help & Support", path: "/help-support", Icon: MdHelpOutline }, +]; + +const MAX_PER_GROUP = 5; + +const norm = (s: unknown) => (typeof s === "string" ? s.toLowerCase() : ""); + +export const CommandPalette = ({ open, onClose }: { open: boolean; onClose: () => void }) => { + if (!open) return null; + return ; +}; + +const CommandPaletteInner = ({ onClose }: { onClose: () => void }) => { + const [q, setQ] = useState(""); + const [activeIdx, setActiveIdx] = useState(0); + const inputRef = useRef(null); + const listRef = useRef(null); + const navigate = useNavigate(); + const userPlan = useAuthStore((s) => s.user?.plan); + + useEffect(() => { + inputRef.current?.focus(); + }, []); + + const groups = useMemo(() => { + const query = q.trim().toLowerCase(); + + const pages: Result[] = PAGES + .filter((p) => !p.plans || (userPlan && p.plans.includes(userPlan))) + .filter((p) => !query || p.label.toLowerCase().includes(query)) + .slice(0, MAX_PER_GROUP) + .map((p) => ({ + kind: "page", + id: p.path, + title: p.label, + subtitle: p.path, + Icon: p.Icon, + onSelect: () => navigate({ to: p.path }), + })); + + const patientsRaw = (queryClient.getQueryData(["patients"]) || []); + const patients: Result[] = patientsRaw + .filter((p) => { + if (!query) return true; + return ( + norm(p.full_name).includes(query) || + norm(p.email).includes(query) || + norm(p.phone_number).includes(query) || + norm(p.cin).includes(query) + ); + }) + .slice(0, MAX_PER_GROUP) + .map((p) => ({ + kind: "patient", + id: p.id, + title: p.full_name, + subtitle: [p.cin, p.email].filter(Boolean).join(" · "), + Icon: MdPerson, + onSelect: () => navigate({ to: "/patients" }), + })); + + const scansRaw = (queryClient.getQueryData(["scanResults"]) || []); + const scans: Result[] = scansRaw + .filter((s) => { + if (!query) return true; + return ( + norm(s.name).includes(query) || + norm(s.scan_code).includes(query) || + norm(s.class).includes(query) || + norm(s.patient?.full_name).includes(query) + ); + }) + .slice(0, MAX_PER_GROUP) + .map((s) => ({ + kind: "scan", + id: s.id, + title: s.name || s.scan_code, + subtitle: [s.scan_code, s.patient?.full_name].filter(Boolean).join(" · "), + Icon: MdImage, + onSelect: () => navigate({ to: "/results/$id", params: { id: s.scan_code } }), + })); + + const reportsRaw = (queryClient.getQueryData(["reports"]) || []); + const reports: Result[] = reportsRaw + .filter((r) => { + if (!query) return true; + return ( + norm(r.title).includes(query) || + norm(r.code).includes(query) || + norm(r.type).includes(query) || + norm(r.patient?.full_name).includes(query) || + norm(r.excerpt).includes(query) + ); + }) + .slice(0, MAX_PER_GROUP) + .map((r) => ({ + kind: "report", + id: r.id, + title: r.title || `Report ${r.code}`, + subtitle: [r.code, r.patient?.full_name].filter(Boolean).join(" · "), + Icon: MdInsertDriveFile, + onSelect: () => navigate({ to: "/reports/$id", params: { id: r.code } }), + })); + + return [ + { label: "Pages", items: pages }, + { label: "Patients", items: patients }, + { label: "Scans", items: scans }, + { label: "Reports", items: reports }, + ].filter((g) => g.items.length > 0); + }, [q, userPlan, navigate]); + + const flat = useMemo(() => groups.flatMap((g) => g.items), [groups]); + + useEffect(() => { + const handler = (e: KeyboardEvent) => { + if (e.key === "Escape") { + e.preventDefault(); + onClose(); + } else if (e.key === "ArrowDown") { + e.preventDefault(); + setActiveIdx((i) => Math.min(flat.length - 1, i + 1)); + } else if (e.key === "ArrowUp") { + e.preventDefault(); + setActiveIdx((i) => Math.max(0, i - 1)); + } else if (e.key === "Enter") { + e.preventDefault(); + const item = flat[activeIdx]; + if (item) { + item.onSelect(); + onClose(); + } + } + }; + window.addEventListener("keydown", handler); + return () => window.removeEventListener("keydown", handler); + }, [flat, activeIdx, onClose]); + + useEffect(() => { + if (!listRef.current) return; + const el = listRef.current.querySelector(`[data-cp-idx="${activeIdx}"]`); + if (el) el.scrollIntoView({ block: "nearest" }); + }, [activeIdx]); + + let runningIdx = -1; + + return ( +
+
e.stopPropagation()} + style={{ + width: "100%", + maxWidth: 600, + background: "white", + borderRadius: 14, + border: "1px solid rgba(195,198,215,0.4)", + boxShadow: "0 20px 60px rgba(15,23,42,0.25)", + overflow: "hidden", + display: "flex", + flexDirection: "column", + maxHeight: "70vh", + }} + > +
+ + { + setQ(e.target.value); + setActiveIdx(0); + }} + placeholder="Search patients, scans, reports, pages…" + style={{ + flex: 1, + border: "none", + outline: "none", + fontSize: 14.5, + color: "#131b2e", + fontFamily: "Inter, sans-serif", + background: "transparent", + }} + /> + + ESC + +
+ +
+ {flat.length === 0 ? ( +
+ {q.trim() + ? "No matches. Try a different search." + : "Start typing to search across pages, patients, scans, and reports."} +
+ ) : ( + groups.map((g) => ( +
+
+ {g.label} +
+ {g.items.map((item) => { + runningIdx += 1; + const idx = runningIdx; + const active = idx === activeIdx; + return ( +
setActiveIdx(idx)} + onClick={() => { + item.onSelect(); + onClose(); + }} + className="flex items-center" + style={{ + gap: 12, + padding: "9px 18px", + cursor: "pointer", + background: active ? "#f2f4f6" : "transparent", + }} + > + +
+
+ {item.title} +
+ {item.subtitle && ( +
+ {item.subtitle} +
+ )} +
+ {active && } +
+ ); + })} +
+ )) + )} +
+ +
+ Showing items already loaded in this session. + + ↑↓ navigate + ↵ open + +
+
+
+ ); +}; diff --git a/client/src/features/dashboard/layout.tsx b/client/src/features/dashboard/layout.tsx index 4872f20..7e44e89 100644 --- a/client/src/features/dashboard/layout.tsx +++ b/client/src/features/dashboard/layout.tsx @@ -25,6 +25,7 @@ import { MI } from "../../components/logo"; import { useLogout } from "../auth/hooks"; import { FREE_LIMIT, REPORT_FREE_LIMIT } from "./Home/constants"; import { NotificationsDropdown } from "./Notifications"; +import { CommandPalette } from "./components/CommandPalette"; // Types type NavItem = { @@ -34,7 +35,6 @@ type NavItem = { badge?: string; badgeType?: "blue" | "orange"; }; - type NavSection = { section: string; items: NavItem[]; @@ -93,11 +93,6 @@ const NAV: NavSection[] = [ label: "API Integration", Icon: MdDescription }, - // { - // id: "/organization/web-hooks", - // label: "Web Hooks", - // Icon: MdSettings - // }, { id: "/organization/audit-logs", label: "Audit Logs", @@ -283,7 +278,20 @@ export const DashboardLayout = ({ children }: { children?: React.ReactNode } = { // User const user = useAuthStore((state) => state.user); - + + // Command palette (⌘K / Ctrl+K) + const [paletteOpen, setPaletteOpen] = useState(false); + useEffect(() => { + const handler = (e: KeyboardEvent) => { + if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "k") { + e.preventDefault(); + setPaletteOpen((o) => !o); + } + }; + window.addEventListener("keydown", handler); + return () => window.removeEventListener("keydown", handler); + }, []); + return (
{/* Search */} -
setPaletteOpen(true)} className="flex items-center transition-all" style={{ gap: 8, @@ -705,7 +715,9 @@ export const DashboardLayout = ({ children }: { children?: React.ReactNode } = { borderRadius: 9, padding: "0 14px", height: 38, - width: 260, + width: "330px", + cursor: "pointer", + textAlign: "left", }} onMouseEnter={(e) => { e.currentTarget.style.borderColor = "rgba(195,198,215,0.5)"; @@ -717,16 +729,16 @@ export const DashboardLayout = ({ children }: { children?: React.ReactNode } = { }} > - + > + {user?.plan === "FREE" ? "Search scans, reports..." : "Search patients, scans, reports..."} + ⌘K -
+ {/* Actions */}
@@ -798,6 +810,8 @@ export const DashboardLayout = ({ children }: { children?: React.ReactNode } = { {children ?? }
+ + setPaletteOpen(false)} />
); }; \ No newline at end of file diff --git a/client/src/router.ts b/client/src/router.ts index dcab9fa..84a9029 100644 --- a/client/src/router.ts +++ b/client/src/router.ts @@ -11,7 +11,6 @@ import { ScanResultsRoute } from "./features/dashboard/ScanResults/route"; import { ScanDetailRoute } from "./features/dashboard/ScanResults/route"; import { ReportsPageRoute, ReportsShareRoute } from "./features/dashboard/Reports/route"; import { ReportsDetailRoute } from "./features/dashboard/Reports/route"; -import { HistoryPageRoute } from "./features/dashboard/History"; import { SettingsPageRoute } from "./features/dashboard/Settings/route"; import { HelpSupportPageRoute } from "./features/dashboard/Help&Support/route"; import { PlansPageRoute } from "./features/dashboard/Plans/route"; @@ -42,7 +41,6 @@ const routeTree = rootRoute.addChildren([ ScanDetailRoute, ReportsPageRoute, ReportsDetailRoute, - HistoryPageRoute, SettingsPageRoute, HelpSupportPageRoute, PlansPageRoute, diff --git a/docker-compose.yml b/docker-compose.yml index 12f5882..a1860e6 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -85,7 +85,7 @@ services: volumes: - redis_data:/data ports: - - "6379:6379" + - "6380:6379" networks: - tumorlens healthcheck: From b680c14944ec55fb5fe031111a2a7d589bd8fcf4 Mon Sep 17 00:00:00 2001 From: elwessdev Date: Wed, 10 Jun 2026 03:10:02 +0100 Subject: [PATCH 18/30] feat: add Help & Support feature with contact form and legal pages --- client/bun.lock | 59 ++ client/package.json | 1 + client/src/features/auth/hooks.ts | 4 +- client/src/features/auth/login.tsx | 7 +- client/src/features/auth/login/LoginForm.tsx | 14 +- client/src/features/auth/register.tsx | 8 +- .../features/auth/register/RegisterForm.tsx | 13 +- .../features/auth/shared/TurnstileWidget.tsx | 38 ++ .../components/ContactChannels.tsx | 35 ++ .../Help&Support/components/ContactForm.tsx | 102 ++++ .../Help&Support/components/FaqSection.tsx | 56 ++ .../Help&Support/components/GuideModal.tsx | 60 ++ .../Help&Support/components/QuickActions.tsx | 31 + .../features/dashboard/Help&Support/data.tsx | 305 ++++++++++ .../features/dashboard/Help&Support/hooks.ts | 17 + .../features/dashboard/Help&Support/index.tsx | 567 +----------------- client/src/features/landing/index.tsx | 82 ++- client/src/features/legal/Compliance.tsx | 158 +++++ client/src/features/legal/PrivacyPolicy.tsx | 145 +++++ client/src/features/legal/Support.tsx | 180 ++++++ client/src/features/legal/TermsOfService.tsx | 137 +++++ .../features/legal/components/LegalLayout.tsx | 250 ++++++++ client/src/features/legal/route.ts | 30 + client/src/router.ts | 10 + client/vite.config.ts | 5 + server/src/Notifications/mail.service.ts | 43 ++ server/src/Support/support.controller.ts | 14 + server/src/Support/support.module.ts | 11 + server/src/Support/support.service.ts | 51 ++ server/src/app.module.ts | 2 + server/src/auth/auth.controller.ts | 7 +- server/src/auth/guards/turnstile.guard.ts | 51 ++ 32 files changed, 1875 insertions(+), 618 deletions(-) create mode 100644 client/src/features/auth/shared/TurnstileWidget.tsx create mode 100644 client/src/features/dashboard/Help&Support/components/ContactChannels.tsx create mode 100644 client/src/features/dashboard/Help&Support/components/ContactForm.tsx create mode 100644 client/src/features/dashboard/Help&Support/components/FaqSection.tsx create mode 100644 client/src/features/dashboard/Help&Support/components/GuideModal.tsx create mode 100644 client/src/features/dashboard/Help&Support/components/QuickActions.tsx create mode 100644 client/src/features/dashboard/Help&Support/data.tsx create mode 100644 client/src/features/dashboard/Help&Support/hooks.ts create mode 100644 client/src/features/legal/Compliance.tsx create mode 100644 client/src/features/legal/PrivacyPolicy.tsx create mode 100644 client/src/features/legal/Support.tsx create mode 100644 client/src/features/legal/TermsOfService.tsx create mode 100644 client/src/features/legal/components/LegalLayout.tsx create mode 100644 client/src/features/legal/route.ts create mode 100644 server/src/Support/support.controller.ts create mode 100644 server/src/Support/support.module.ts create mode 100644 server/src/Support/support.service.ts create mode 100644 server/src/auth/guards/turnstile.guard.ts diff --git a/client/bun.lock b/client/bun.lock index c19abf4..60de920 100644 --- a/client/bun.lock +++ b/client/bun.lock @@ -5,11 +5,16 @@ "": { "name": "client", "dependencies": { + "@marsidev/react-turnstile": "^1.5.3", "@tailwindcss/vite": "^4.2.2", "@tanstack/react-query": "^5.96.2", "@tanstack/react-router": "^1.168.7", "antd": "^6.3.4", + "antd-img-crop": "^4.30.0", "axios": "1.14.0", + "html2canvas": "^1.4.1", + "jspdf": "^4.2.1", + "qrcode.react": "^4.2.0", "react": "^19.2.4", "react-dom": "^19.2.4", "react-icons": "^5.6.0", @@ -132,6 +137,8 @@ "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="], + "@marsidev/react-turnstile": ["@marsidev/react-turnstile@1.5.3", "", { "peerDependencies": { "react": "^17.0.2 || ^18.0.0 || ^19.0", "react-dom": "^17.0.2 || ^18.0.0 || ^19.0" } }, "sha512-8Dij2jiNGNczq1U4EKpO4do2XepcTPxSMc2ZzvHndO+gcp68tvMULm27z2P99rGkdB89hc3452NZeu2Rti4g6A=="], + "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.1", "", { "dependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1", "@tybys/wasm-util": "^0.10.1" } }, "sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A=="], "@oxc-project/types": ["@oxc-project/types@0.122.0", "", {}, "sha512-oLAl5kBpV4w69UtFZ9xqcmTi+GENWOcPF7FCrczTiBbmC0ibXxCwyvZGbO39rCVEuLGAZM84DH0pUIyyv/YJzA=="], @@ -344,10 +351,16 @@ "@types/node": ["@types/node@24.12.0", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ=="], + "@types/pako": ["@types/pako@2.0.4", "", {}, "sha512-VWDCbrLeVXJM9fihYodcLiIv0ku+AlOa/TQ1SvYOaBuyrSKgEcro95LJyIsJ4vSo6BXIxOKxiJAat04CmST9Fw=="], + + "@types/raf": ["@types/raf@3.4.3", "", {}, "sha512-c4YAvMedbPZ5tEyxzQdMoOhhJ4RD3rngZIdwC2/qDN3d7JpEhB6fiBRKVY1lg5B7Wk+uPBjn5f39j1/2MY1oOw=="], + "@types/react": ["@types/react@19.2.14", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w=="], "@types/react-dom": ["@types/react-dom@19.2.3", "", { "peerDependencies": { "@types/react": "^19.2.0" } }, "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ=="], + "@types/trusted-types": ["@types/trusted-types@2.0.7", "", {}, "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw=="], + "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.57.2", "", { "dependencies": { "@eslint-community/regexpp": "^4.12.2", "@typescript-eslint/scope-manager": "8.57.2", "@typescript-eslint/type-utils": "8.57.2", "@typescript-eslint/utils": "8.57.2", "@typescript-eslint/visitor-keys": "8.57.2", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.57.2", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-NZZgp0Fm2IkD+La5PR81sd+g+8oS6JwJje+aRWsDocxHkjyRw0J5L5ZTlN3LI1LlOcGL7ph3eaIUmTXMIjLk0w=="], "@typescript-eslint/parser": ["@typescript-eslint/parser@8.57.2", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.57.2", "@typescript-eslint/types": "8.57.2", "@typescript-eslint/typescript-estree": "8.57.2", "@typescript-eslint/visitor-keys": "8.57.2", "debug": "^4.4.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-30ScMRHIAD33JJQkgfGW1t8CURZtjc2JpTrq5n2HFhOefbAhb7ucc7xJwdWcrEtqUIYJ73Nybpsggii6GtAHjA=="], @@ -380,6 +393,8 @@ "antd": ["antd@6.3.4", "", { "dependencies": { "@ant-design/colors": "^8.0.1", "@ant-design/cssinjs": "^2.1.2", "@ant-design/cssinjs-utils": "^2.1.2", "@ant-design/fast-color": "^3.0.1", "@ant-design/icons": "^6.1.0", "@ant-design/react-slick": "~2.0.0", "@babel/runtime": "^7.28.4", "@rc-component/cascader": "~1.14.0", "@rc-component/checkbox": "~2.0.0", "@rc-component/collapse": "~1.2.0", "@rc-component/color-picker": "~3.1.1", "@rc-component/dialog": "~1.8.4", "@rc-component/drawer": "~1.4.2", "@rc-component/dropdown": "~1.0.2", "@rc-component/form": "~1.8.0", "@rc-component/image": "~1.8.0", "@rc-component/input": "~1.1.2", "@rc-component/input-number": "~1.6.2", "@rc-component/mentions": "~1.6.0", "@rc-component/menu": "~1.2.0", "@rc-component/motion": "^1.3.1", "@rc-component/mutate-observer": "^2.0.1", "@rc-component/notification": "~1.2.0", "@rc-component/pagination": "~1.2.0", "@rc-component/picker": "~1.9.1", "@rc-component/progress": "~1.0.2", "@rc-component/qrcode": "~1.1.1", "@rc-component/rate": "~1.0.1", "@rc-component/resize-observer": "^1.1.1", "@rc-component/segmented": "~1.3.0", "@rc-component/select": "~1.6.15", "@rc-component/slider": "~1.0.1", "@rc-component/steps": "~1.2.2", "@rc-component/switch": "~1.0.3", "@rc-component/table": "~1.9.1", "@rc-component/tabs": "~1.7.0", "@rc-component/textarea": "~1.1.2", "@rc-component/tooltip": "~1.4.0", "@rc-component/tour": "~2.3.0", "@rc-component/tree": "~1.2.4", "@rc-component/tree-select": "~1.8.0", "@rc-component/trigger": "^3.9.0", "@rc-component/upload": "~1.1.0", "@rc-component/util": "^1.10.0", "clsx": "^2.1.1", "dayjs": "^1.11.11", "scroll-into-view-if-needed": "^3.1.0", "throttle-debounce": "^5.0.2" }, "peerDependencies": { "react": ">=18.0.0", "react-dom": ">=18.0.0" } }, "sha512-Bu6JivPP7bFfYIdVj+61dxhwSOz+A3m0W7PlDasFGC3H3sNMYQ9gJXZoo11/rQh7pTlOQa351q5Ig/zjI98XYw=="], + "antd-img-crop": ["antd-img-crop@4.30.0", "", { "dependencies": { "react-easy-crop": "^5.5.6", "tslib": "^2.8.1" }, "peerDependencies": { "antd": ">=4.0.0", "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-fjpwyCNKtKr22AQcENBix5Y+P8ECM80Ivk/Yn7kF9D0XltYBGJHg+3yycxcGq7ATgnl7pgPYDvN2VzKleogCLQ=="], + "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], "asynckit": ["asynckit@0.4.0", "", {}, "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="], @@ -390,6 +405,8 @@ "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + "base64-arraybuffer": ["base64-arraybuffer@1.0.2", "", {}, "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ=="], + "baseline-browser-mapping": ["baseline-browser-mapping@2.10.11", "", { "bin": { "baseline-browser-mapping": "dist/cli.cjs" } }, "sha512-DAKrHphkJyiGuau/cFieRYhcTFeK/lBuD++C7cZ6KZHbMhBrisoi+EvhQ5RZrIfV5qwsW8kgQ07JIC+MDJRAhg=="], "brace-expansion": ["brace-expansion@1.1.13", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w=="], @@ -402,6 +419,8 @@ "caniuse-lite": ["caniuse-lite@1.0.30001781", "", {}, "sha512-RdwNCyMsNBftLjW6w01z8bKEvT6e/5tpPVEgtn22TiLGlstHOVecsX2KHFkD5e/vRnIE4EGzpuIODb3mtswtkw=="], + "canvg": ["canvg@3.0.11", "", { "dependencies": { "@babel/runtime": "^7.12.5", "@types/raf": "^3.4.0", "core-js": "^3.8.3", "raf": "^3.4.1", "regenerator-runtime": "^0.13.7", "rgbcolor": "^1.0.1", "stackblur-canvas": "^2.0.0", "svg-pathdata": "^6.0.3" } }, "sha512-5ON+q7jCTgMp9cjpu4Jo6XbvfYwSB2Ow3kzHKfIyJfaCAOHLbdKPQqGKgfED/R5B+3TFFfe8pegYA+b423SRyA=="], + "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], "chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="], @@ -422,8 +441,12 @@ "cookie-es": ["cookie-es@2.0.0", "", {}, "sha512-RAj4E421UYRgqokKUmotqAwuplYw15qtdXfY+hGzgCJ/MBjCVZcSoHK/kH9kocfjRjcDME7IiDWR/1WX1TM2Pg=="], + "core-js": ["core-js@3.49.0", "", {}, "sha512-es1U2+YTtzpwkxVLwAFdSpaIMyQaq0PBgm3YD1W3Qpsn1NAmO3KSgZfu+oGSWVu6NvLHoHCV/aYcsE5wiB7ALg=="], + "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], + "css-line-break": ["css-line-break@2.1.0", "", { "dependencies": { "utrie": "^1.0.2" } }, "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w=="], + "csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="], "dayjs": ["dayjs@1.11.20", "", {}, "sha512-YbwwqR/uYpeoP4pu043q+LTDLFBLApUP6VxRihdfNTqu4ubqMlGDLd6ErXhEgsyvY0K6nCs7nggYumAN+9uEuQ=="], @@ -436,6 +459,8 @@ "detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], + "dompurify": ["dompurify@3.4.8", "", { "optionalDependencies": { "@types/trusted-types": "^2.0.7" } }, "sha512-yb1cEmaOum7wFvOCSQxyfgVlv5D47Rc30iZWoMpbDIWTnJ6grDDQyu2KFJzB2k7u0pMuJcQ1zphH//fFnw2tjQ=="], + "dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="], "electron-to-chromium": ["electron-to-chromium@1.5.328", "", {}, "sha512-QNQ5l45DzYytThO21403XN3FvK0hOkWDG8viNf6jqS42msJ8I4tGDSpBCgvDRRPnkffafiwAym2X2eHeGD2V0w=="], @@ -480,8 +505,12 @@ "fast-levenshtein": ["fast-levenshtein@2.0.6", "", {}, "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="], + "fast-png": ["fast-png@6.4.0", "", { "dependencies": { "@types/pako": "^2.0.3", "iobuffer": "^5.3.2", "pako": "^2.1.0" } }, "sha512-kAqZq1TlgBjZcLr5mcN6NP5Rv4V2f22z00c3g8vRrwkcqjerx7BEhPbOnWCPqaHUl2XWQBJQvOT/FQhdMT7X/Q=="], + "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="], + "fflate": ["fflate@0.8.3", "", {}, "sha512-tbZNuJrLwGUp3zshBtdy4W+ORxZuIh8a5ilyIEQDC5rY1f3U20JMry0Ll3WBzU58EZKsEuJFXhb5gwv8CsPvgA=="], + "file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="], "find-up": ["find-up@5.0.0", "", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="], @@ -524,6 +553,8 @@ "hermes-parser": ["hermes-parser@0.25.1", "", { "dependencies": { "hermes-estree": "0.25.1" } }, "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA=="], + "html2canvas": ["html2canvas@1.4.1", "", { "dependencies": { "css-line-break": "^2.1.0", "text-segmentation": "^1.0.3" } }, "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA=="], + "ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="], "immutable": ["immutable@5.1.5", "", {}, "sha512-t7xcm2siw+hlUM68I+UEOK+z84RzmN59as9DZ7P1l0994DKUWV7UXBMQZVxaoMSRQ+PBZbHCOoBt7a2wxOMt+A=="], @@ -532,6 +563,8 @@ "imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="], + "iobuffer": ["iobuffer@5.4.0", "", {}, "sha512-DRebOWuqDvxunfkNJAlc3IzWIPD5xVxwUNbHr7xKB8E6aLJxIPfNX3CoMJghcFjpv6RWQsrcJbghtEwSPoJqMA=="], + "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], @@ -560,6 +593,8 @@ "json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="], + "jspdf": ["jspdf@4.2.1", "", { "dependencies": { "@babel/runtime": "^7.28.6", "fast-png": "^6.2.0", "fflate": "^0.8.1" }, "optionalDependencies": { "canvg": "^3.0.11", "core-js": "^3.6.0", "dompurify": "^3.3.1", "html2canvas": "^1.0.0-rc.5" } }, "sha512-YyAXyvnmjTbR4bHQRLzex3CuINCDlQnBqoSYyjJwTP2x9jDLuKDzy7aKUl0hgx3uhcl7xzg32agn5vlie6HIlQ=="], + "keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="], "levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="], @@ -614,18 +649,24 @@ "node-releases": ["node-releases@2.0.36", "", {}, "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA=="], + "normalize-wheel": ["normalize-wheel@1.0.1", "", {}, "sha512-1OnlAPZ3zgrk8B91HyRj+eVv+kS5u+Z0SCsak6Xil/kmgEia50ga7zfkumayonZrImffAxPU/5WcyGhzetHNPA=="], + "optionator": ["optionator@0.9.4", "", { "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.5" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="], "p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="], "p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="], + "pako": ["pako@2.1.0", "", {}, "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug=="], + "parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="], "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="], "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], + "performance-now": ["performance-now@2.1.0", "", {}, "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow=="], + "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], "picomatch": ["picomatch@4.0.4", "", {}, "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A=="], @@ -638,18 +679,28 @@ "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], + "qrcode.react": ["qrcode.react@4.2.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-QpgqWi8rD9DsS9EP3z7BT+5lY5SFhsqGjpgW5DY/i3mK4M9DTBNz3ErMi8BWYEfI3L0d8GIbGmcdFAS1uIRGjA=="], + + "raf": ["raf@3.4.1", "", { "dependencies": { "performance-now": "^2.1.0" } }, "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA=="], + "react": ["react@19.2.4", "", {}, "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ=="], "react-dom": ["react-dom@19.2.4", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.4" } }, "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ=="], + "react-easy-crop": ["react-easy-crop@5.5.7", "", { "dependencies": { "normalize-wheel": "^1.0.1", "tslib": "^2.0.1" }, "peerDependencies": { "react": ">=16.4.0", "react-dom": ">=16.4.0" } }, "sha512-kYo4NtMeXFQB7h1U+h5yhUkE46WQbQdq7if54uDlbMdZHdRgNehfvaFrXnFw5NR1PNoUOJIfTwLnWmEx/MaZnA=="], + "react-icons": ["react-icons@5.6.0", "", { "peerDependencies": { "react": "*" } }, "sha512-RH93p5ki6LfOiIt0UtDyNg/cee+HLVR6cHHtW3wALfo+eOHTp8RnU2kRkI6E+H19zMIs03DyxUG/GfZMOGvmiA=="], "react-is": ["react-is@18.3.1", "", {}, "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="], "readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="], + "regenerator-runtime": ["regenerator-runtime@0.13.11", "", {}, "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="], + "resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="], + "rgbcolor": ["rgbcolor@1.0.1", "", {}, "sha512-9aZLIrhRaD97sgVhtJOW6ckOEh6/GnvQtdVNfdZ6s67+3/XwLS9lBcQYzEEhYVeUowN7pRzMLsyGhK2i/xvWbw=="], + "rolldown": ["rolldown@1.0.0-rc.12", "", { "dependencies": { "@oxc-project/types": "=0.122.0", "@rolldown/pluginutils": "1.0.0-rc.12" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.0.0-rc.12", "@rolldown/binding-darwin-arm64": "1.0.0-rc.12", "@rolldown/binding-darwin-x64": "1.0.0-rc.12", "@rolldown/binding-freebsd-x64": "1.0.0-rc.12", "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.12", "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.12", "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.12", "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.12", "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.12", "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.12", "@rolldown/binding-linux-x64-musl": "1.0.0-rc.12", "@rolldown/binding-openharmony-arm64": "1.0.0-rc.12", "@rolldown/binding-wasm32-wasi": "1.0.0-rc.12", "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.12", "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.12" }, "bin": { "rolldown": "bin/cli.mjs" } }, "sha512-yP4USLIMYrwpPHEFB5JGH1uxhcslv6/hL0OyvTuY+3qlOSJvZ7ntYnoWpehBxufkgN0cvXxppuTu5hHa/zPh+A=="], "sass": ["sass@1.98.0", "", { "dependencies": { "chokidar": "^4.0.0", "immutable": "^5.1.5", "source-map-js": ">=0.6.2 <2.0.0" }, "optionalDependencies": { "@parcel/watcher": "^2.4.1" }, "bin": { "sass": "sass.js" } }, "sha512-+4N/u9dZ4PrgzGgPlKnaaRQx64RO0JBKs9sDhQ2pLgN6JQZ25uPQZKQYaBJU48Kd5BxgXoJ4e09Dq7nMcOUW3A=="], @@ -670,6 +721,8 @@ "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], + "stackblur-canvas": ["stackblur-canvas@2.7.0", "", {}, "sha512-yf7OENo23AGJhBriGx0QivY5JP6Y1HbrrDI6WLt6C5auYZXlQrheoY8hD4ibekFKz1HOfE48Ww8kMWMnJD/zcQ=="], + "string-convert": ["string-convert@0.2.1", "", {}, "sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A=="], "strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="], @@ -678,10 +731,14 @@ "supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], + "svg-pathdata": ["svg-pathdata@6.0.3", "", {}, "sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw=="], + "tailwindcss": ["tailwindcss@4.2.2", "", {}, "sha512-KWBIxs1Xb6NoLdMVqhbhgwZf2PGBpPEiwOqgI4pFIYbNTfBXiKYyWoTsXgBQ9WFg/OlhnvHaY+AEpW7wSmFo2Q=="], "tapable": ["tapable@2.3.2", "", {}, "sha512-1MOpMXuhGzGL5TTCZFItxCc0AARf1EZFQkGqMm7ERKj8+Hgr5oLvJOVFcC+lRmR8hCe2S3jC4T5D7Vg/d7/fhA=="], + "text-segmentation": ["text-segmentation@1.0.3", "", { "dependencies": { "utrie": "^1.0.2" } }, "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw=="], + "throttle-debounce": ["throttle-debounce@5.0.2", "", {}, "sha512-B71/4oyj61iNH0KeCamLuE2rmKuTO5byTOSVwECM5FA7TiAiAW+UqTKZ9ERueC4qvgSttUhdmq1mXC3kJqGX7A=="], "tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="], @@ -704,6 +761,8 @@ "use-sync-external-store": ["use-sync-external-store@1.6.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w=="], + "utrie": ["utrie@1.0.2", "", { "dependencies": { "base64-arraybuffer": "^1.0.2" } }, "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw=="], + "vite": ["vite@8.0.3", "", { "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.4", "postcss": "^8.5.8", "rolldown": "1.0.0-rc.12", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "@vitejs/devtools": "^0.1.0", "esbuild": "^0.27.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "@vitejs/devtools", "esbuild", "jiti", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-B9ifbFudT1TFhfltfaIPgjo9Z3mDynBTJSUYxTjOQruf/zHH+ezCQKcoqO+h7a9Pw9Nm/OtlXAiGT1axBgwqrQ=="], "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], diff --git a/client/package.json b/client/package.json index a5c1067..5c48a33 100644 --- a/client/package.json +++ b/client/package.json @@ -10,6 +10,7 @@ "preview": "vite preview" }, "dependencies": { + "@marsidev/react-turnstile": "^1.5.3", "@tailwindcss/vite": "^4.2.2", "@tanstack/react-query": "^5.96.2", "@tanstack/react-router": "^1.168.7", diff --git a/client/src/features/auth/hooks.ts b/client/src/features/auth/hooks.ts index 99423b6..c163656 100644 --- a/client/src/features/auth/hooks.ts +++ b/client/src/features/auth/hooks.ts @@ -5,7 +5,7 @@ import { queryClient } from "../../main"; // Login export const useSignin = () => useMutation({ - mutationFn: async (data: { email: string; password: string; twoFactorCode?: string }) => { + mutationFn: async (data: { email: string; password: string; twoFactorCode?: string; turnstileToken?: string | null }) => { const response = await axiosInstance.post("/auth/login", data); return response.data; }, @@ -13,7 +13,7 @@ export const useSignin = () => useMutation({ // Register export const useSignup = () => useMutation({ - mutationFn: async (data: { email: string; password: string; username: string }) => { + mutationFn: async (data: { email: string; password: string; username: string; turnstileToken?: string | null }) => { const response = await axiosInstance.post("/auth/register", data); return response.data; }, diff --git a/client/src/features/auth/login.tsx b/client/src/features/auth/login.tsx index ac3da9a..3a1bf98 100644 --- a/client/src/features/auth/login.tsx +++ b/client/src/features/auth/login.tsx @@ -14,11 +14,12 @@ export const LoginPage = () => { const [errorMsg, setErrorMsg] = useState(null); const [twoFactorStep, setTwoFactorStep] = useState(false); const [credentials, setCredentials] = useState<{ email: string; password: string } | null>(null); + const [turnstileReset, setTurnstileReset] = useState(0); - const handleSubmit = (values: { email: string; password: string; remember: boolean }) => { + const handleSubmit = (values: { email: string; password: string; remember: boolean; turnstileToken: string | null }) => { setErrorMsg(null); signin( - { email: values.email, password: values.password }, + { email: values.email, password: values.password, turnstileToken: values.turnstileToken }, { onSuccess: data => { if (data?.twoFactorRequired) { @@ -30,6 +31,7 @@ export const LoginPage = () => { navigate({ to: "/" }); }, onError: error => { + setTurnstileReset(n => n + 1); const e = error as { response?: { data?: { message?: string } } }; setErrorMsg(e.response?.data?.message ?? "Invalid email or password. Please try again."); }, @@ -86,6 +88,7 @@ export const LoginPage = () => { errorMsg={errorMsg} onSubmit={handleSubmit} onValuesChange={() => setErrorMsg(null)} + resetSignal={turnstileReset} /> )}
diff --git a/client/src/features/auth/login/LoginForm.tsx b/client/src/features/auth/login/LoginForm.tsx index 535a341..e6c9d9c 100644 --- a/client/src/features/auth/login/LoginForm.tsx +++ b/client/src/features/auth/login/LoginForm.tsx @@ -1,11 +1,14 @@ +import { useState } from "react"; import { Button, Checkbox, Form, Input } from "antd"; import { Link } from "@tanstack/react-router"; +import { TurnstileWidget, turnstileEnabled } from "../shared/TurnstileWidget"; interface Props { loading: boolean; errorMsg: string | null; - onSubmit: (values: { email: string; password: string; remember: boolean }) => void; + onSubmit: (values: { email: string; password: string; remember: boolean; turnstileToken: string | null }) => void; onValuesChange: () => void; + resetSignal?: number; } const GoogleSvg = () => ( @@ -33,8 +36,9 @@ const labelStyle = { letterSpacing: "0.05em", }; -export const LoginForm = ({ loading, errorMsg, onSubmit, onValuesChange }: Props) => { +export const LoginForm = ({ loading, errorMsg, onSubmit, onValuesChange, resetSignal }: Props) => { const [form] = Form.useForm(); + const [turnstileToken, setTurnstileToken] = useState(null); return ( <> @@ -52,7 +56,7 @@ export const LoginForm = ({ loading, errorMsg, onSubmit, onValuesChange }: Props
onSubmit({ ...values, turnstileToken })} onValuesChange={onValuesChange} requiredMark={false} > @@ -110,13 +114,15 @@ export const LoginForm = ({ loading, errorMsg, onSubmit, onValuesChange }: Props )} + +

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 - - - - - - - - - - - - - - - - - - - - - - - diff --git a/client/public/favicon_io/site.webmanifest b/client/public/site.webmanifest similarity index 100% rename from client/public/favicon_io/site.webmanifest rename to client/public/site.webmanifest diff --git a/client/src/features/dashboard/ScanResults/hooks.ts b/client/src/features/dashboard/ScanResults/hooks.ts index 1fa60f7..8625ffc 100644 --- a/client/src/features/dashboard/ScanResults/hooks.ts +++ b/client/src/features/dashboard/ScanResults/hooks.ts @@ -64,7 +64,7 @@ export const useGenerateReport = () => { // Poll job status — stops automatically once the job reaches a terminal state type JobStatus = - | { success: boolean; state: 'waiting' | 'active' | 'delayed' | 'prioritized' } + | { success: boolean; state: 'waiting' | 'active' | 'delayed' | 'paused' | 'waiting-children' | (string & {}) } | { success: boolean; state: 'completed'; result: { reportId: string; code: string } } | { success: boolean; state: 'failed'; error: string }; diff --git a/server/src/Report/report.service.ts b/server/src/Report/report.service.ts index 876644e..8f4d2f0 100644 --- a/server/src/Report/report.service.ts +++ b/server/src/Report/report.service.ts @@ -50,7 +50,7 @@ export class ReportService { attempts: 3, backoff: { type: 'exponential', delay: 5000 }, }); - + return { success: true, jobId: job.id }; } catch (error) { console.error('Error queueing report:', error); From 1c8fcb5aa909e572e90419c12ae3ae2df247e876 Mon Sep 17 00:00:00 2001 From: elwessdev Date: Fri, 8 May 2026 14:27:41 +0100 Subject: [PATCH 08/30] fix deploy bugs --- client/src/features/dashboard/ScanResults/ReportCard.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/client/src/features/dashboard/ScanResults/ReportCard.tsx b/client/src/features/dashboard/ScanResults/ReportCard.tsx index 9a05f91..bfcc0da 100644 --- a/client/src/features/dashboard/ScanResults/ReportCard.tsx +++ b/client/src/features/dashboard/ScanResults/ReportCard.tsx @@ -133,21 +133,22 @@ export const ReportCard = ({ scan }: { scan: ScanDetail }) => { useEffect(() => { if (!jobStatus) return; - if (jobStatus.state === 'completed') { + if (jobStatus.state === 'completed' && 'result' in jobStatus) { clearPendingJob(scan.uid); setJobId(null); if (isFree) incrementTotalReports(); setStepsDone(GENERATE_STEPS.length); queryClient.invalidateQueries({ queryKey: ['scanDetail', scan.uid] }); queryClient.invalidateQueries({ queryKey: ['reports'] }); + const code = jobStatus.result.code; setTimeout(() => { setState("done"); queryClient.invalidateQueries({ queryKey: ['scanResults'] }); - navigate({ to: `/reports/${jobStatus.result.code}` }); + navigate({ to: `/reports/${code}` }); }, 600); } - if (jobStatus.state === 'failed') { + if (jobStatus.state === 'failed' && 'error' in jobStatus) { clearPendingJob(scan.uid); setJobId(null); setState("error"); From abe1a0b22ebe26ccea00351f222d7b93df292460 Mon Sep 17 00:00:00 2001 From: elwessdev Date: Fri, 8 May 2026 14:39:30 +0100 Subject: [PATCH 09/30] Update Landing page --- client/src/features/landing/index.tsx | 121 ++++++++++++++++++-------- client/src/index.css | 26 ++++++ 2 files changed, 112 insertions(+), 35 deletions(-) diff --git a/client/src/features/landing/index.tsx b/client/src/features/landing/index.tsx index 77e1cd1..2c0455b 100644 --- a/client/src/features/landing/index.tsx +++ b/client/src/features/landing/index.tsx @@ -5,7 +5,23 @@ import Logo from "../../components/logo"; import { MI } from "../../components/logo"; import { DashboardLayout } from "../dashboard/layout"; import { PLANS, type PlanFeature } from "../dashboard/Plans/helpers"; -import { useState, useEffect } from "react"; +import { useState, useEffect, useRef } from "react"; + +const useInView = (threshold = 0.12) => { + const ref = useRef(null); + const [visible, setVisible] = useState(false); + useEffect(() => { + const el = ref.current; + if (!el) return; + const obs = new IntersectionObserver( + ([e]) => { if (e.isIntersecting) { setVisible(true); obs.disconnect(); } }, + { threshold }, + ); + obs.observe(el); + return () => obs.disconnect(); + }, [threshold]); + return { ref, visible }; +}; const renderFeatures = (features: PlanFeature[], theme: "light" | "dark" = "light") => { @@ -120,6 +136,10 @@ const scrollTo = (id: string) => { const LandingPage = () => { const [scrolled, setScrolled] = useState(false); + const [heroVisible, setHeroVisible] = useState(false); + const { ref: featuresRef, visible: featuresVisible } = useInView(); + const { ref: stepsRef, visible: stepsVisible } = useInView(); + const { ref: ctaRef, visible: ctaVisible } = useInView(); useEffect(() => { const onScroll = () => setScrolled(window.scrollY > 10); @@ -127,6 +147,11 @@ const LandingPage = () => { return () => window.removeEventListener("scroll", onScroll); }, []); + useEffect(() => { + const t = setTimeout(() => setHeroVisible(true), 80); + return () => clearTimeout(t); + }, []); + return (