feat(simulations): GET /simulations/:id — lecture rapport avec auth + REPORT_NOT_READY

This commit is contained in:
Hermann_Kitio 2026-04-20 04:41:24 +03:00
parent 6ca2412304
commit 0680a6382f
3 changed files with 215 additions and 0 deletions

View file

@ -1,6 +1,7 @@
import { supabase } from '../lib/supabase.js'
import { canUserSimulate, getPlanPermissions } from '../lib/access.js'
import type { Plan } from '../lib/access.js'
import type { EERapport } from '../lib/deepseek.js'
import type { AuthProfile } from '../middleware/auth.js'
export type Tache = 'EE_T1' | 'EE_T2' | 'EE_T3' | 'EO_T1' | 'EO_T3' | 'EO_T2_LIVE'
@ -74,3 +75,69 @@ export async function create(
return { data: data as CreateResult }
}
// EERapport et EORapport ont la même structure depuis l'étape A —
// on utilise EERapport comme représentation canonique du rapport parsé.
export type GetByIdResult = EERapport & {
simulation_id: string
tache: Tache
mode: Mode
created_at: string
}
type GetByIdError = {
error: true
code: string
message: string
status: number
}
export async function getById(
id: string,
profile: AuthProfile
): Promise<{ data: GetByIdResult } | GetByIdError> {
const { data, error } = await supabase
.from('productions')
.select('id, user_id, tache, mode, score, nclc, rapport, created_at')
.eq('id', id)
.single()
if (error || !data) {
return {
error: true,
code: 'SIMULATION_NOT_FOUND',
message: 'Simulation introuvable.',
status: 404,
}
}
if (data.user_id !== profile.id) {
return {
error: true,
code: 'AUTH_REQUIRED',
message: 'Cette simulation ne vous appartient pas.',
status: 401,
}
}
if (data.rapport === null) {
return {
error: true,
code: 'REPORT_NOT_READY',
message: "Le rapport n'est pas encore disponible pour cette simulation.",
status: 404,
}
}
const rapport = JSON.parse(data.rapport) as EERapport
return {
data: {
...rapport,
simulation_id: data.id,
tache: data.tache as Tache,
mode: data.mode as Mode,
created_at: data.created_at,
},
}
}