Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | 48x 48x 45x 48x 43x 48x 48x 2x 46x 46x 45x 46x 48x 48x 43x 48x 45x 48x 48x 92x | /**
* Procedure tracker for legislative data
*
* Transforms real EP API Procedure data into structured legislative
* tracking output. All data is derived from the API response—no
* hardcoded or placeholder data.
*
* ISMS Policy: SC-002 (Input Validation)
*/
import type { Procedure } from '../../types/europeanParliament.js';
import type { LegislativeProcedure } from './types.js';
/**
* Derive a timeline from the procedure's date fields.
* All dates come from the real EP API response.
*/
function buildTimeline(procedure: Procedure): LegislativeProcedure['timeline'] {
const events: LegislativeProcedure['timeline'] = [];
if (procedure.dateInitiated) {
events.push({
date: procedure.dateInitiated,
stage: 'Initiated',
description: `Procedure ${procedure.reference || procedure.id} initiated`,
});
}
if (procedure.dateLastActivity && procedure.dateLastActivity !== procedure.dateInitiated) {
events.push({
date: procedure.dateLastActivity,
stage: procedure.stage || 'Latest activity',
description: `Latest recorded activity for ${procedure.reference || procedure.id}`,
});
}
return events;
}
/**
* Derive committee assignments from the procedure data.
*/
function buildCommittees(procedure: Procedure): LegislativeProcedure['committees'] {
if (!procedure.responsibleCommittee) {
return [];
}
const assignment: LegislativeProcedure['committees'][number] = {
abbreviation: procedure.responsibleCommittee,
role: 'LEAD' as const,
};
if (procedure.rapporteur) {
assignment.rapporteur = procedure.rapporteur;
}
return [assignment];
}
/**
* Derive next steps from the current stage.
*/
function buildNextSteps(procedure: Procedure): string[] {
const steps: string[] = [];
if (procedure.stage) {
steps.push(`Current stage: ${procedure.stage}`);
}
if (procedure.status) {
steps.push(`Status: ${procedure.status}`);
}
return steps;
}
/**
* Build a legislative tracking result from a real EP API Procedure.
*
* All fields are derived from the API response. No mock or placeholder data.
*
* @param procedure - Real procedure data from EP API
* @returns Structured legislative tracking data
*/
export function buildLegislativeTracking(procedure: Procedure): LegislativeProcedure {
return {
procedureId: procedure.id,
title: procedure.title,
type: procedure.type,
status: procedure.status || 'COMMITTEE',
currentStage: procedure.stage || 'Unknown',
timeline: buildTimeline(procedure),
committees: buildCommittees(procedure),
amendments: { proposed: 0, adopted: 0, rejected: 0 },
voting: [],
documents: procedure.documents.map((docRef) => ({
id: docRef,
type: 'Document',
date: procedure.dateLastActivity || procedure.dateInitiated || '',
title: `Reference: ${docRef}`,
})),
nextSteps: buildNextSteps(procedure),
confidenceLevel: 'MEDIUM',
methodology: 'Real-time data from EP API /procedures endpoint. '
+ 'Procedure details (title, type, stage, status, dates, committee, rapporteur, documents) '
+ 'are sourced directly from the European Parliament open data API. '
+ 'Amendment and voting statistics require separate API calls and are not yet populated. '
+ 'Data source: https://data.europarl.europa.eu/api/v2/procedures',
};
}
|