From 5e9ab2126308d149b1d0b35a5e820afbded1ba09 Mon Sep 17 00:00:00 2001 From: Alexandre Fauquette <45398769+alexfauquette@users.noreply.github.com> Date: Sun, 25 Aug 2024 23:31:27 +0200 Subject: [PATCH] =?UTF-8?q?Am=C3=A9liore=20les=20pages=20deput=C3=A9s=20(#?= =?UTF-8?q?54)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Improve amendements for deputes * Ajouter la page sur les travaux parlementaire * remove duplicated mandats * fix mandats * reshape depute tabs * use relative path * get update from ORM * Ajout des questions au gouvernements --- .env.example | 10 +- .../debat/[compteRenduRef]/DebateTimeline.tsx | 4 +- .../[compteRenduRef]/DebateTranscript.tsx | 12 +- .../[id]/debat/[compteRenduRef]/page.tsx | 2 +- app/depute/[slug]/Mandats.tsx | 35 +- app/depute/[slug]/Tabs.tsx | 6 + app/depute/[slug]/[tab]/Activites.tsx | 5 - app/depute/[slug]/[tab]/Amendements.tsx | 49 -- app/depute/[slug]/[tab]/Travaux.tsx | 20 - app/depute/[slug]/[tab]/page.tsx | 22 - app/depute/[slug]/amendements/page.tsx | 74 ++++ app/depute/[slug]/layout.tsx | 4 +- app/depute/[slug]/page.tsx | 9 +- app/depute/[slug]/qag/QuestionCard.tsx | 146 ++++++ app/depute/[slug]/qag/page.tsx | 40 ++ app/depute/[slug]/travaux/ShowJSON.tsx | 17 + app/depute/[slug]/travaux/page.tsx | 174 ++++++++ .../{[tab]/Votes.tsx => votes/page.tsx} | 4 +- components/folders/AmendementCard.tsx | 45 +- components/folders/DebatTab/ParoleItem.tsx | 2 +- copy.js | 17 + package-lock.json | 17 + package.json | 7 +- prisma/models/acteur.prisma | 9 +- prisma/models/agenda.prisma | 3 + prisma/models/amendement.prisma | 10 +- prisma/models/debat.prisma | 28 +- prisma/models/document.prisma | 27 +- prisma/models/dossier.prisma | 7 + prisma/models/mandat.prisma | 5 +- prisma/models/organe.prisma | 4 +- prisma/models/scrutin.prisma | 2 +- prisma/models/texte_loi.prisma | 148 +++++++ prisma/swagger/json-schema.json | 419 ++++++++++++++++-- 34 files changed, 1191 insertions(+), 192 deletions(-) delete mode 100644 app/depute/[slug]/[tab]/Activites.tsx delete mode 100644 app/depute/[slug]/[tab]/Amendements.tsx delete mode 100644 app/depute/[slug]/[tab]/Travaux.tsx delete mode 100644 app/depute/[slug]/[tab]/page.tsx create mode 100644 app/depute/[slug]/amendements/page.tsx create mode 100644 app/depute/[slug]/qag/QuestionCard.tsx create mode 100644 app/depute/[slug]/qag/page.tsx create mode 100644 app/depute/[slug]/travaux/ShowJSON.tsx create mode 100644 app/depute/[slug]/travaux/page.tsx rename app/depute/[slug]/{[tab]/Votes.tsx => votes/page.tsx} (93%) create mode 100644 copy.js create mode 100644 prisma/models/texte_loi.prisma diff --git a/.env.example b/.env.example index 0f05fec..f6e646a 100644 --- a/.env.example +++ b/.env.example @@ -1,6 +1,14 @@ # .env.local + +## settings to the DB for knext (will be removed) DB_HOST=51.159.207.103 DB_PORT=1695 DB_USER=default_user DB_PASSWORD=... -DB_DATABASE=tricoteuses \ No newline at end of file +DB_DATABASE=tricoteuses + +## setting to the prisma db +TRICOTEUSES_ASSEMBLEE_API_DB_URL="postgresql://username:password@host:port/dbname?schema=public" + +## Path to tricoteuses-api-assemblee-orm +TRICOTEUSES_ASSEMBLEE_API_REPO="/home/.../tricoteuses-api-assemblee-orm" \ No newline at end of file diff --git a/app/[legislature]/dossier/[id]/debat/[compteRenduRef]/DebateTimeline.tsx b/app/[legislature]/dossier/[id]/debat/[compteRenduRef]/DebateTimeline.tsx index b9cc7a5..71c6b55 100644 --- a/app/[legislature]/dossier/[id]/debat/[compteRenduRef]/DebateTimeline.tsx +++ b/app/[legislature]/dossier/[id]/debat/[compteRenduRef]/DebateTimeline.tsx @@ -21,14 +21,14 @@ export const DebateTimeline = ({ paragraphs }: DebateTimelineProps) => ( }, }} > - {paragraphs.map(({ hash, codeGrammaire, acteur, roleDebat, texte }) => { + {paragraphs.map(({ hash, codeGrammaire, acteurRef, roleDebat, texte }) => { switch (codeGrammaire) { case "PAROLE_GENERIQUE": case "INTERRUPTION_1_10": return ( diff --git a/app/[legislature]/dossier/[id]/debat/[compteRenduRef]/DebateTranscript.tsx b/app/[legislature]/dossier/[id]/debat/[compteRenduRef]/DebateTranscript.tsx index c6d38dd..3f0063a 100644 --- a/app/[legislature]/dossier/[id]/debat/[compteRenduRef]/DebateTranscript.tsx +++ b/app/[legislature]/dossier/[id]/debat/[compteRenduRef]/DebateTranscript.tsx @@ -17,7 +17,7 @@ import { WORDS_PER_MINUTES } from "@/components/const"; import { Acteur, Organe, Paragraphe } from "@prisma/client"; export type ParagrapheWithActeur = Paragraphe & { - acteur: null | (Acteur & { groupeParlementaire: null | Organe }); + acteurRef: null | (Acteur & { groupeParlementaire: null | Organe }); }; function getWordsPerGroup(paragraphs: ParagrapheWithActeur[]) { @@ -30,18 +30,18 @@ function getWordsPerGroup(paragraphs: ParagrapheWithActeur[]) { } > = {}; paragraphs.forEach((paragraphe) => { - const { codeGrammaire, acteur, texte } = paragraphe; + const { codeGrammaire, acteurRef, texte } = paragraphe; if ( codeGrammaire !== "PAROLE_GENERIQUE" || - !acteur || - !acteur.groupeParlementaire || - !acteur.groupeParlementaireUid || + !acteurRef || + !acteurRef.groupeParlementaire || + !acteurRef.groupeParlementaireUid || !texte ) { return; } - const groupeParlementaire = acteur.groupeParlementaire; + const groupeParlementaire = acteurRef.groupeParlementaire; const wordCount = texte.split(" ").length; if (groups[groupeParlementaire.uid]) { diff --git a/app/[legislature]/dossier/[id]/debat/[compteRenduRef]/page.tsx b/app/[legislature]/dossier/[id]/debat/[compteRenduRef]/page.tsx index 216786b..9b88497 100644 --- a/app/[legislature]/dossier/[id]/debat/[compteRenduRef]/page.tsx +++ b/app/[legislature]/dossier/[id]/debat/[compteRenduRef]/page.tsx @@ -39,7 +39,7 @@ async function getParagraphesUnCached( valeurPtsOdj: index.toString(), }, include: { - acteur: { + acteurRef: { include: { groupeParlementaire: true }, }, }, diff --git a/app/depute/[slug]/Mandats.tsx b/app/depute/[slug]/Mandats.tsx index 2b20a37..25820fc 100644 --- a/app/depute/[slug]/Mandats.tsx +++ b/app/depute/[slug]/Mandats.tsx @@ -18,7 +18,8 @@ const order = ["COMPER", "COMNL", "GE", "GA"]; type MandatsPerType = Record< string, - (Pick & Pick)[] + (Pick & + Pick)[] >; export default function Mandats({ @@ -34,15 +35,17 @@ export default function Mandats({ if (!organe) { return acc; } - const { libQualiteSex, typeOrgane } = mandat; + const { libQualiteSex, typeOrgane, organeRefUid, dateFin } = mandat; return { ...acc, [typeOrgane]: [ ...(acc[typeOrgane] ?? []), { + organeRefUid, libelle: organe?.libelle, libQualiteSex, + dateFin, }, ], }; @@ -64,14 +67,26 @@ export default function Mandats({ - {mandatsPerType[type].map(({ libelle, libQualiteSex }) => ( - - - {libelle} - {libQualiteSex && ` (${libQualiteSex})`} - - - ))} + {mandatsPerType[type] + .filter(({ libQualiteSex, organeRefUid }) => { + if (libQualiteSex !== "Membre") { + return true; + } + return ( + // Display "Membre" mandat if it's the unique mandat in the organe (avoid duplicate with membre + president, or secretaire, ...) + mandatsPerType[type].filter( + (item) => item.organeRefUid === organeRefUid + ).length === 1 + ); + }) + .map(({ libelle, libQualiteSex }) => ( + + + {libelle} + {libQualiteSex && ` (${libQualiteSex})`} + + + ))} ))} diff --git a/app/depute/[slug]/Tabs.tsx b/app/depute/[slug]/Tabs.tsx index fe335be..0b2201f 100644 --- a/app/depute/[slug]/Tabs.tsx +++ b/app/depute/[slug]/Tabs.tsx @@ -35,6 +35,12 @@ export default function DeputeTabs({ slug }: { slug: string }) { component={Link} href={`/depute/${slug}/votes`} /> + ); } diff --git a/app/depute/[slug]/[tab]/Activites.tsx b/app/depute/[slug]/[tab]/Activites.tsx deleted file mode 100644 index 2388dd7..0000000 --- a/app/depute/[slug]/[tab]/Activites.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import React from "react"; - -export default async function Activites(props: { deputeSlug: string }) { - return

Activites

; -} diff --git a/app/depute/[slug]/[tab]/Amendements.tsx b/app/depute/[slug]/[tab]/Amendements.tsx deleted file mode 100644 index 76cc88c..0000000 --- a/app/depute/[slug]/[tab]/Amendements.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import React from "react"; - -import Stack from "@mui/material/Stack"; - -import AmendementCard from "@/components/folders/AmendementCard"; -import { prisma } from "@/prisma"; - -async function getDeputeAmendementUnCached(slug: string) { - try { - return await prisma.acteur.findFirst({ - where: { slug }, - - // Verifier que ca fonctionne quadn on aura les amendements dans la DB - include: { amendements: true, groupeParlementaire: true }, - }); - } catch (error) { - console.error(`Error fetching amendement from depute ${slug}:`, error); - throw error; - } -} - -export const getDeputeAmendement = React.cache(getDeputeAmendementUnCached); - -export default async function Amendements(props: { deputeSlug: string }) { - const deputeWithAmendements = await getDeputeAmendement(props.deputeSlug); - - const { amendements, ...depute } = deputeWithAmendements!; - - return ( - -

Amendements

- {amendements && - amendements - .sort((a, b) => - Number.parseInt(a.numeroOrdreDepot || "") < - Number.parseInt(b.numeroOrdreDepot || "") - ? -1 - : 1 - ) - .map((amendement) => ( - - ))} -
- ); -} diff --git a/app/depute/[slug]/[tab]/Travaux.tsx b/app/depute/[slug]/[tab]/Travaux.tsx deleted file mode 100644 index bbc590a..0000000 --- a/app/depute/[slug]/[tab]/Travaux.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// import { getDeputeDocuments } from "@/repository/database"; -import { Stack, Typography } from "@mui/material"; -import React from "react"; - -export default async function Travaux(props: { deputeSlug: string }) { - // const { depute, documents = [] } = await getDeputeDocuments(props.deputeSlug); - - // if (documents.length === 0) { - return

Pas de documents trouvé.

; - // } - // return ( - // - // {documents.map((documents) => ( - // - // {documents.titrePrincipalCourt} - // - // ))} - // - // ); -} diff --git a/app/depute/[slug]/[tab]/page.tsx b/app/depute/[slug]/[tab]/page.tsx deleted file mode 100644 index c121303..0000000 --- a/app/depute/[slug]/[tab]/page.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import React from "react"; -import Amendements from "./Amendements"; -import Votes from "./Votes"; -import Travaux from "./Travaux"; -import Activites from "./Activites"; - -export default function Page({ - params, -}: { - params: { slug: string; tab: string }; -}) { - switch (params.tab) { - case "amendements": - return ; - case "votes": - return ; - case "travaux": - return ; - default: - return ; - } -} diff --git a/app/depute/[slug]/amendements/page.tsx b/app/depute/[slug]/amendements/page.tsx new file mode 100644 index 0000000..786d03d --- /dev/null +++ b/app/depute/[slug]/amendements/page.tsx @@ -0,0 +1,74 @@ +import React from "react"; + +import Stack from "@mui/material/Stack"; + +import AmendementCard from "@/components/folders/AmendementCard"; +import { prisma } from "@/prisma"; + +async function getDeputeAmendementUnCached(slug: string) { + try { + return await prisma.acteur.findFirst({ + where: { slug }, + select: { + amendements: { + include: { texteLegislatifRef: { select: { numNotice: true } } }, + }, + }, + }); + } catch (error) { + console.error(`Error fetching amendement from depute ${slug}:`, error); + throw error; + } +} + +const getDeputeAmendement = React.cache(getDeputeAmendementUnCached); + +export default async function Amendements({ + params, +}: { + params: { slug: string }; +}) { + const deputeWithAmendements = await getDeputeAmendement(params.slug); + + const { amendements } = deputeWithAmendements!; + + return ( + +

Amendements

+ {amendements && + amendements + .sort((a, b) => + Number.parseInt(a.numeroOrdreDepot || "") < + Number.parseInt(b.numeroOrdreDepot || "") + ? -1 + : 1 + ) + .map((amendement) => { + const numeroNotice = amendement.texteLegislatifRef?.numNotice; + const section = amendement.divisionArticleDesignationCourte; + // const subSection = amendement.alineaDesignation; + + const article = [ + section, + // subSection + ] + .filter((item) => item !== null) + .join(" "); + + const titre = `Amendement N°${amendement.numeroOrdreDepot}${ + numeroNotice == null + ? "" + : ` au text N°${numeroNotice}${article ? ` - ${article}` : ""}` + }`; + return ( + + ); + })} +
+ ); +} diff --git a/app/depute/[slug]/layout.tsx b/app/depute/[slug]/layout.tsx index 1bf511c..63efb87 100644 --- a/app/depute/[slug]/layout.tsx +++ b/app/depute/[slug]/layout.tsx @@ -50,7 +50,7 @@ export default async function Page({ // A décider: Faut il afficher les mandats passé? // Exemple: la partissipation à des commission d'enquête const mandasEnCours = depute.mandats?.filter( - (mandat) => true //mandat.dateFin === null + (mandat) => mandat.dateFin === null ); return ( @@ -78,7 +78,7 @@ export default async function Page({ <>
Fin de mandat le{" "} - {new Date(circonscription.dateFin).toLocaleDateString()} + {new Date(circonscription.dateFin).toLocaleDateString("fr-FR")} )} diff --git a/app/depute/[slug]/page.tsx b/app/depute/[slug]/page.tsx index 71726e3..2fb3a93 100644 --- a/app/depute/[slug]/page.tsx +++ b/app/depute/[slug]/page.tsx @@ -1,10 +1,5 @@ import React from "react"; -import Activites from "./[tab]/Activites"; -export default function Page({ - params, -}: { - params: { slug: string; tab: string }; -}) { - return ; +export default function Page({ params }: { params: { slug: string } }) { + return

Activités

; } diff --git a/app/depute/[slug]/qag/QuestionCard.tsx b/app/depute/[slug]/qag/QuestionCard.tsx new file mode 100644 index 0000000..7bddbbf --- /dev/null +++ b/app/depute/[slug]/qag/QuestionCard.tsx @@ -0,0 +1,146 @@ +"use client"; +import * as React from "react"; + +import Typography from "@mui/material/Typography"; +import Stack from "@mui/material/Stack"; +import Accordion from "@mui/material/Accordion"; +import AccordionDetails from "@mui/material/AccordionDetails"; +import AccordionSummary from "@mui/material/AccordionSummary"; + +import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; + +import { Organe, Question } from "@prisma/client"; +import StatusChip from "@/components/StatusChip"; + +type QuestionCardProps = { + question: Question & { minIntRef: Organe | null }; +}; + +export default function QuestionCard(props: QuestionCardProps) { + const { + question: { + uid, + type, + numero, + dateDepot, + dateCloture, + titre, + rubrique, + texteQuestion, + erratumQuestion, + texteReponse, + erratumReponse, + minIntRef, + }, + } = props; + + const pannelId = `${uid}-pannel`; + const headerId = `${uid}-header`; + + return ( + ({ + borderBottom: `solid ${theme.palette.divider} 1px`, + borderRadius: 0, + })} + > + } + > + + {titre && {titre}} + {rubrique && } + {type && } + + + + + N°{numero} + {texteQuestion && ( + + {texteQuestion} + + )} + {texteReponse && ( + + {texteReponse} + + )} + {erratumQuestion && ( + + {erratumQuestion} + + )} + {erratumReponse && ( + + {erratumReponse} + + )} + + + Envoyé à:  + + {minIntRef?.libelleAbrege} + + + + + Date de dépôt:  + + {dateDepot && dateDepot.toLocaleDateString("fr-FR")} + + + + + Date de cloture:  + + {dateCloture && dateCloture.toLocaleDateString("fr-FR")} + + + + + + + ); +} diff --git a/app/depute/[slug]/qag/page.tsx b/app/depute/[slug]/qag/page.tsx new file mode 100644 index 0000000..449298d --- /dev/null +++ b/app/depute/[slug]/qag/page.tsx @@ -0,0 +1,40 @@ +import React from "react"; + +import { prisma } from "@/prisma"; +import QuestionCard from "./QuestionCard"; + +async function getDeputeQuestionsUnCached(slug: string) { + try { + return await prisma.acteur.findFirst({ + where: { slug }, + include: { + questions: { + include: { + minIntRef: true, + }, + }, + }, + }); + } catch (error) { + console.error(`Error fetching QAG from depute ${slug}:`, error); + throw error; + } +} + +const getDeputeQuestions = React.cache(getDeputeQuestionsUnCached); + +export default async function Votes({ params }: { params: { slug: string } }) { + const deputeWithQuestions = await getDeputeQuestions(params.slug); + + if (!deputeWithQuestions) { + return

Deputé inconnu

; + } + const { questions = [] } = deputeWithQuestions; + return ( +
+ {questions?.map((question) => { + return ; + })} +
+ ); +} diff --git a/app/depute/[slug]/travaux/ShowJSON.tsx b/app/depute/[slug]/travaux/ShowJSON.tsx new file mode 100644 index 0000000..824bea1 --- /dev/null +++ b/app/depute/[slug]/travaux/ShowJSON.tsx @@ -0,0 +1,17 @@ +import Accordion from "@mui/material/Accordion"; +import AccordionDetails from "@mui/material/AccordionDetails"; +import AccordionSummary from "@mui/material/AccordionSummary"; +import Typography from "@mui/material/Typography"; +import React from "react"; +export function ShowJSON({ item, titre }: { item: any; titre: string }) { + return ( + + + {titre} + + +
{JSON.stringify(item, null, 2)}
+
+
+ ); +} diff --git a/app/depute/[slug]/travaux/page.tsx b/app/depute/[slug]/travaux/page.tsx new file mode 100644 index 0000000..a4c69ea --- /dev/null +++ b/app/depute/[slug]/travaux/page.tsx @@ -0,0 +1,174 @@ +import React from "react"; + +import Stack from "@mui/material/Stack"; +import Typography from "@mui/material/Typography"; +import Link from "next/link"; + +import { prisma } from "@/prisma"; + +async function getDeputeActiviteUnCached(slug: string) { + try { + return await prisma.acteur.findFirst({ + where: { slug }, + + select: { + // To investigate. Je ne sais pas pourquoi ce champ contient un sous ensemble de `documents` + // auteurs: { + // include: { + // documentRef: { + // select: { + // auteurPrincipal: true, + // titrePrincipalCourt: true, + // coSignataires: true, + // }, + // }, + // }, + // }, + documents: true, + // initiateurActeLegislatif: true, + dossiers: { include: { dossierRef: true } }, + // rapporteurs: true, + }, + }); + } catch (error) { + console.error(`Error fetching amendement from depute ${slug}:`, error); + throw error; + } +} + +const getDeputeActivite = React.cache(getDeputeActiviteUnCached); + +export default async function Amendements({ + params, +}: { + params: { slug: string }; +}) { + const deputeWithAmendements = await getDeputeActivite(params.slug); + + const { + // auteurs, + documents, + // initiateurActeLegislatif, + dossiers, + // rapporteurs, + // ...depute + } = deputeWithAmendements!; + + const propositionDeLoi = documents.filter( + (doc) => doc.classeCode === "PIONLOI" + ); + const rapports = documents.filter( + (doc) => doc.classeCode === "RAPPORT" || doc.classeCode === "RAPINF" + ); + + const resolutions = documents.filter((doc) => doc.classeCode === "RES"); + + return ( + + Travaux legislatifs + + Propositions de loi + + {(!propositionDeLoi || propositionDeLoi.length === 0) && ( + + Aucune proposition de loi trouvée + + )} +
    + {propositionDeLoi.map((docs) => ( +
  • + {docs.titrePrincipalCourt} + + {docs.dateCreation?.toLocaleDateString()} + +
  • + ))} +
+ + Rapports + + {(!rapports || rapports.length === 0) && ( + Aucun rapport trouvé + )} +
    + {rapports.map((docs) => ( +
  • + {docs.titrePrincipalCourt} + + {docs.dateCreation?.toLocaleDateString()} + +
  • + ))} +
+ + Resolutions + + {(!resolutions || resolutions.length === 0) && ( + Aucune resolution trouvée + )} +
    + {resolutions.map((docs) => ( +
  • + {docs.titrePrincipalCourt} + + {docs.dateCreation?.toLocaleDateString()} + +
  • + ))} +
+ + + Dossier legislatifs initié + + {(!dossiers || dossiers.length === 0) && ( + Aucune resolution trouvée + )} +
    + {dossiers.map((dossier) => ( +
  • + + {dossier.dossierRef?.titre} + + {/* TODO: Ajouter le status du dossier legislatif ou la date de derniere modification */} +
  • + ))} +
+
+ ); +} diff --git a/app/depute/[slug]/[tab]/Votes.tsx b/app/depute/[slug]/votes/page.tsx similarity index 93% rename from app/depute/[slug]/[tab]/Votes.tsx rename to app/depute/[slug]/votes/page.tsx index 82eaf89..bd12c56 100644 --- a/app/depute/[slug]/[tab]/Votes.tsx +++ b/app/depute/[slug]/votes/page.tsx @@ -44,8 +44,8 @@ async function getDeputeVotesUnCached(slug: string) { const getDeputeVotes = React.cache(getDeputeVotesUnCached); -export default async function Votes(props: { deputeSlug: string }) { - const deputeWithVote = await getDeputeVotes(props.deputeSlug); +export default async function Votes({ params }: { params: { slug: string } }) { + const deputeWithVote = await getDeputeVotes(params.slug); if (!deputeWithVote) { return

Deputé inconnu

; diff --git a/components/folders/AmendementCard.tsx b/components/folders/AmendementCard.tsx index 074d9f2..8182bbc 100644 --- a/components/folders/AmendementCard.tsx +++ b/components/folders/AmendementCard.tsx @@ -32,10 +32,11 @@ function getStatus(label: string | null) { type AmendementCardProps = { amendement: Amendement; depute: null | (Acteur & { groupeParlementaire: Organe | null }); + titre?: string; }; export default function AmendementCard(props: AmendementCardProps) { - const { amendement, depute } = props; + const { amendement, depute, titre } = props; // TODO: utiliser la base cosignataires amendement pour avoir le nombre et les noms const nbSignataires = amendement.signatairesLibelle @@ -65,20 +66,23 @@ export default function AmendementCard(props: AmendementCardProps) { spacing={1} sx={{ width: "100%", mr: 2 }} > - + smallGroupColor + sx={{ flexGrow: 1 }} + /> + )} + {titre && {titre}} )} + {amendement.exposeSommaire && ( + + )} {/* Examiné par:  diff --git a/components/folders/DebatTab/ParoleItem.tsx b/components/folders/DebatTab/ParoleItem.tsx index 1011174..7ca0714 100644 --- a/components/folders/DebatTab/ParoleItem.tsx +++ b/components/folders/DebatTab/ParoleItem.tsx @@ -12,7 +12,7 @@ import CircleDiv from "@/icons/CircleDiv"; import { ParagrapheWithActeur } from "@/app/[legislature]/dossier/[id]/debat/[compteRenduRef]/DebateTranscript"; interface ParoleItemProps { - acteur: ParagrapheWithActeur["acteur"]; + acteur: ParagrapheWithActeur["acteurRef"]; roleDebat: string | null; texte: string | null; } diff --git a/copy.js b/copy.js new file mode 100644 index 0000000..138882b --- /dev/null +++ b/copy.js @@ -0,0 +1,17 @@ +require("dotenv").config(); +const fs = require("fs"); + +function main() { + fs.cpSync( + `${process.env.TRICOTEUSES_ASSEMBLEE_API_REPO}/prisma/models`, + `./prisma/models`, + { recursive: true }, + (err) => { + if (err) { + console.error(err); + } + } + ); +} + +main(); diff --git a/package-lock.json b/package-lock.json index 174d2c2..8fc9710 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ "@mui/material": "^5.14.18", "@prisma/client": "^5.16.1", "@types/lodash": "^4.17.4", + "dotenv": "^16.3.1", "knex": "^3.1.0", "lodash": "^4.17.21", "next": "14.0.1", @@ -2251,6 +2252,17 @@ "csstype": "^3.0.2" } }, + "node_modules/dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, "node_modules/electron-to-chromium": { "version": "1.4.576", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.576.tgz", @@ -7444,6 +7456,11 @@ "csstype": "^3.0.2" } }, + "dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==" + }, "electron-to-chromium": { "version": "1.4.576", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.576.tgz", diff --git a/package.json b/package.json index 04e7083..688ce15 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,9 @@ "dev": "next dev", "build": "next build", "start": "next start", - "lint": "next lint" + "lint": "next lint", + "typescript": "tsc -p tsconfig.json", + "import-prisma": "node copy.js" }, "dependencies": { "@emotion/react": "^11.11.1", @@ -16,6 +18,7 @@ "@mui/material": "^5.14.18", "@prisma/client": "^5.16.1", "@types/lodash": "^4.17.4", + "dotenv": "^16.3.1", "knex": "^3.1.0", "lodash": "^4.17.21", "next": "14.0.1", @@ -38,6 +41,6 @@ "typescript": "^5.5.4" }, "prisma": { - "schema": "prisma/models" + "schema": "./prisma/models" } } diff --git a/prisma/models/acteur.prisma b/prisma/models/acteur.prisma index c071923..0536b1b 100644 --- a/prisma/models/acteur.prisma +++ b/prisma/models/acteur.prisma @@ -64,8 +64,15 @@ model Acteur { questions Question[] rapporteurs Rapporteur[] suppletions Suppleant[] + interventions Paragraphe[] vecteurRecherche Unsupported("tsvector")? @default(dbgenerated("to_tsvector('french'::regconfig, ((immutable_unaccent((COALESCE(prenom, ''::text))::character varying) || ' '::text) || immutable_unaccent((COALESCE(nom, ''::text))::character varying)))")) - paroles Paragraphe[] + + /// Lois présentées au nom de cet acteur (e.g. un premier ministre). + loisPortees TexteLoi[] @relation("loisPortees") + /// Lois présentées par cet acteur. + loisPresentees TexteLoi[] @relation("loisPresentees") + /// Lois signées par cet acteur. + loisSignees TexteLoi[] @relation("loisSignees") @@index([vecteurRecherche], type: Gin) @@index([actif]) diff --git a/prisma/models/agenda.prisma b/prisma/models/agenda.prisma index 7278181..a73ee9c 100644 --- a/prisma/models/agenda.prisma +++ b/prisma/models/agenda.prisma @@ -53,6 +53,8 @@ model Agenda { convocationOdj String[] /// Texte court décrivant l'objet de la réunion. resumeOdj String[] + /// Nombre de participants à la réunion + nombreParticipants Int? @default(0) organeReunionRefUid String? /// Organes à l'initiative de la réunion. organeDemandeurRefUid String? @@ -66,6 +68,7 @@ model Agenda { pointsOdj PointOdj[] scrutins Scrutin[] amendements Amendement[] + debats Debat[] @@index([vecteurRecherche], type: Gin) @@index([organeDemandeurRefUid]) diff --git a/prisma/models/amendement.prisma b/prisma/models/amendement.prisma index 6f68161..25cb8a6 100644 --- a/prisma/models/amendement.prisma +++ b/prisma/models/amendement.prisma @@ -12,8 +12,6 @@ model Amendement { prefixeOrganeExamen String? numeroRect String? examenRef String? - /// Identifiant unique du texte législatif visé par l'amendement. - texteLegislatifRefUid String? /// Lorsque tous les amendements visant un texte de loi sont triés sur cette clé, cela détermine leur ordre d'appel. triAmendement String? /// Le contenu de ce champ n'est pas défini. @@ -102,19 +100,23 @@ model Amendement { idDiscussion String? typePosition String? accordGouvernementDepotHorsDelai String? - documentUid String? /// Exposé sommaire des motifs justifiant l'amendement, au format HTML. exposeSommaireHtml String? /// Description exhaustive des modifications apportées au texte original, au format HTML. dispositifHtml String? /// Nombre de co-signataires nombreCoSignataires Int @default(0) + /// Identifiant du dossier de loi lié à l'amendement + dossierRefUid String? + /// Identifiant unique du texte législatif (document) visé par l'amendement. + texteLegislatifRefUid String? /// Identifiant du scrutin lié à l'amendement scrutinRefUid String? @unique vecteurRecherche Unsupported("tsvector")? @default(dbgenerated("to_tsvector('french'::regconfig, ((((immutable_unaccent((COALESCE(dispositif, ''::text))::character varying) || ' '::text) || immutable_unaccent((COALESCE(\"exposeSommaire\", ''::text))::character varying)) || ' '::text) || immutable_unaccent((COALESCE(\"divisionArticleDesignationCourte\", ''::text))::character varying)))")) texteLegislatifRef Document? @relation(fields: [texteLegislatifRefUid], references: [uid]) + dossierRef Dossier? @relation(fields: [dossierRefUid], references: [uid]) acteurRef Acteur? @relation(fields: [acteurRefUid], references: [uid]) scrutinRef Scrutin? @relation(fields: [scrutinRefUid], references: [uid]) amendementParentRef Amendement? @relation("amendementParentRef", fields: [amendementParentRefUid], references: [uid], onDelete: Restrict, onUpdate: Restrict) @@ -129,7 +131,7 @@ model Amendement { @@index([acteurRefUid]) @@index([seanceRefUid]) @@index([scrutinRefUid]) - @@index([documentUid]) + @@index([dossierRefUid]) @@index([texteLegislatifRefUid]) @@index([amendementParentRefUid]) @@index([auteurRapporteurOrganeRefUid]) diff --git a/prisma/models/debat.prisma b/prisma/models/debat.prisma index 0cd9bbd..49a028a 100644 --- a/prisma/models/debat.prisma +++ b/prisma/models/debat.prisma @@ -1,14 +1,14 @@ /// Compte rendu des débats en séance. model Debat { /// Identifiant unique. - uid String @id + uid String @id /// Hachage de l'obejt. - hash String @unique + hash String @unique typeAssemblee String legislature String - seanceRef String + reunionRefUid String? sessionRef String - dateSeance String + dateSeance DateTime? dateSeanceJour String numSeance String numSeanceJour String @@ -22,8 +22,12 @@ model Debat { validite String quantiemesJournee String quantiemesSession String - paragraphes Paragraphe[] - sommaires SommaireDebat[] + + reunionRef Agenda? @relation(fields: [reunionRefUid], references: [uid]) + paragraphes Paragraphe[] + sommaires SommaireDebat[] + + @@index([reunionRefUid]) } /// Sommaire d'une séance de débat. @@ -42,7 +46,7 @@ model SommaireDebat { } model Paragraphe { - /// Hachage de l'obejt. + /// Hachage de l'objet. hash String @unique debatRefUid String adt String? @@ -52,8 +56,8 @@ model Paragraphe { codeParole String? codeStyle String? decision String? - acteurRef String? - mandatRef String? + acteurRefUid String? + mandatRefUid String? idNominationOe String? idNominationOp String? idPreparation String? @@ -72,10 +76,12 @@ model Paragraphe { texte String? stime String? vecteurRecherche Unsupported("tsvector")? @default(dbgenerated("to_tsvector('french'::regconfig, immutable_unaccent((COALESCE(texte, ''::text))::character varying))")) + acteurRef Acteur? @relation(fields: [acteurRefUid], references: [uid]) + mandatRef Mandat? @relation(fields: [mandatRefUid], references: [uid]) debatRef Debat @relation(fields: [debatRefUid], references: [uid]) - acteur Acteur? @relation(fields: [acteurRef], references: [uid]) @@index([vecteurRecherche], type: Gin) @@index([debatRefUid]) - @@index([acteurRef]) + @@index([acteurRefUid]) + @@index([mandatRefUid]) } diff --git a/prisma/models/document.prisma b/prisma/models/document.prisma index 5de189d..967e691 100644 --- a/prisma/models/document.prisma +++ b/prisma/models/document.prisma @@ -1,3 +1,26 @@ +enum ClasseCode { + /// Projet de loi (initiative du gouvernement) + PRJLOI + /// Proposition de loi (initiative du parlement) + PIONLOI + /// Proposition de Resolution + PIONRES + // Avis + AVIS + /// Motion (motion de censure article 49-2 de la consitution) + MOTION + /// Allocution + ALLOCUTION + /// Declaration du gouvernement (souvent utilisation de l'article 49-3) + DECLARATION + /// Rapport d'une commission + RAPPORT + /// Rapport d'information + RAPINF + /// Resolution (positionnement pris par l'assemblée sans impact legislatif) + RES +} + model Document { /// Hachage de l'objet hash String @unique @@ -8,11 +31,11 @@ model Document { /// Identifiant unique du document. uid String @id /// Code unique pour traitement automatisé. - classeCode String + classeCode ClasseCode /// Signification du code. classeLibelle String /// True si le document est un projet ou une proposition de loi. - texteDeLoi Boolean? + texteLoi Boolean? /// Code unique pour traitement automatisé. depotCode String /// Signification du code. diff --git a/prisma/models/dossier.prisma b/prisma/models/dossier.prisma index 8cadff8..4a0040c 100644 --- a/prisma/models/dossier.prisma +++ b/prisma/models/dossier.prisma @@ -8,6 +8,12 @@ model Dossier { xsiType String? /// Numéro de la législature. legislature String + /// Date de dépôt du texte + dateDepot DateTime? + /// Date du dernier acte législatif lié au texte + dateDernierActe DateTime? + /// Code du dernier acte législatif + codeDernierActe String? /// URL du dossier législatif sur le site du Sénat. senatChemin String? /// Titre du dossier législatif. @@ -35,6 +41,7 @@ model Dossier { plf EtudePlf[] initiateurs InitiateurDossier[] actesLegislatifs ActeLegislatif[] + amendements Amendement[] documents Document[] pointsOdj PointOdj[] diff --git a/prisma/models/mandat.prisma b/prisma/models/mandat.prisma index ad7759e..7062319 100644 --- a/prisma/models/mandat.prisma +++ b/prisma/models/mandat.prisma @@ -9,6 +9,8 @@ model Mandat { organeRefUid String? legislature String? typeOrgane String + /// Vrai si le mandat est en cours + actif Boolean? dateDebut DateTime datePublication DateTime? dateFin DateTime? @@ -43,7 +45,8 @@ model Mandat { mandatRemplacementRef Mandat? @relation("MandatRemplace") missionPrecedenteRef Mandat? @relation("MissionSequence", fields: [missionPrecedenteRefUid], references: [uid], onDelete: Restrict, onUpdate: Restrict) missionSuivanteRef Mandat? @relation("MissionSequence") - question Question[] + questions Question[] + interventions Paragraphe[] suppleantRef Suppleant? votes Vote[] diff --git a/prisma/models/organe.prisma b/prisma/models/organe.prisma index cc35742..a5e5ef0 100644 --- a/prisma/models/organe.prisma +++ b/prisma/models/organe.prisma @@ -16,7 +16,8 @@ model Organe { secretaire02 String? regimeJuridique String? siteInternet String? - nombreReunionsAnnuelles String? + nombreReunionsAnnuelles Int? + nombreMembres Int? @default(0) positionPolitique String? preseance String? couleurAssociee String? @@ -45,6 +46,7 @@ model Organe { membresGroupeParlementaire Acteur[] @relation("Acteur_GroupeParlementaire") parlementairesCirsconscription Acteur[] @relation("Acteur_Circonscription") communes Commune[] + textesLoi TexteLoi[] @@index([vecteurRecherche], type: Gin) @@index([organeParentRefUid]) diff --git a/prisma/models/scrutin.prisma b/prisma/models/scrutin.prisma index a0421fa..1708796 100644 --- a/prisma/models/scrutin.prisma +++ b/prisma/models/scrutin.prisma @@ -113,7 +113,7 @@ model Vote { hash String @unique /// Identifiant unique (uid) de l'acteur. acteurRefUid String - positionVote PositionVote + positionVote PositionVote? /// Raison pour laquelle un acteur n'as pas voté malgré sa présence. MG pour membre du gouvernement, PAN pour président de l'Assemblée nationale, PSE pour président de séance. causePositionVote String? /// Identifiant unique (uid) du mandat qui donne à l'acteur le droit de vote. diff --git a/prisma/models/texte_loi.prisma b/prisma/models/texte_loi.prisma new file mode 100644 index 0000000..c937c95 --- /dev/null +++ b/prisma/models/texte_loi.prisma @@ -0,0 +1,148 @@ +/// Texte de loi rédigé par des acteurs. +model TexteLoi { + /// Identifiant unique. + uid String @id + /// Hachage de l'objet + hash String @unique + + /// Titre du texte de loi + titre String + /// Chambre du parlementaire (assemblée ou sénat) + chambre String? + + /// Numéro de législature. + legislature String + + /// Identifiant de la commission associée à ce texte. + commissionRefUid String + /// `true` si la procédure est accélérée ; `false` sinon. + procedureAcceleree Boolean @default(false) + + /// Date de la constitution associée. + dateConstitution DateTime? + /// Date de dépôt à l'Assemblée Nationale + dateDepot DateTime? + + /// Numéro du texte + numero String + + /// Commission chargée du texte de loi. + commission Organe @relation(fields: [commissionRefUid], references: [uid]) + + /// Texte de loi présenté au nom de... (e.g. nom du Premier ministre) + presenteeAuNomDe Acteur[] @relation("loisPortees") + + /// Texte de loi présenté par un ensemble de députés. + presenteePar Acteur[] @relation("loisPresentees") + + /// Signataires de cette loi. + signataires Acteur[] @relation("loisSignees") + + /// Sommaire du texte de loi. + sommaire SommaireLoi[] + + /// Citation de l'exposé des motifs, si elle existe. + exposeMotifsCitation String? + + /// Description des articles de l'exposé des motifs, si elle existe. + exposeMotifsDescriptionArticles String? + + /// Contenu de l'exposé des motifs comprenant la description des articles. + exposeMotifsContenu String? + + /// Liste des articles du texte de loi. + articles Article[] + + @@index([commissionRefUid]) +} + +/// Sommaire d'un texte de loi. +model SommaireLoi { + /// Identifiant unique d'un sommaire. + uid String @id + /// Hachage de l'objet. + hash String @unique + + division DivisionType + + /// Numéro de la division. + numeroDivision Int + + /// Ordre de la division dans le document. + sequence String + + /// Titre de la division. + titre String + + /// Identifiant de la division parente. + parent String? + + /// Identifiant unique de référence du texte de loi associé. + texteLoiRefUid String + + /// Référence du texte de loi associé. + texteLoiRef TexteLoi @relation(fields: [texteLoiRefUid], references: [uid]) + + @@index([texteLoiRefUid]) +} + +enum DivisionType { + Titre + Chapitre + Section + SousSection +} + +/// Article d'un texte de loi. +model Article { + /// Identifiant unique d'un article. + uid String @id + + /// Hachage de l'objet. + hash String @unique + + /// Numéro de l'article. + numero Int? + + /// Numéro des articles (dans de rare cas, il y a un groupement d'articles). + numeros Int[] + + /// Cardinal de l'article (e.g. er, bis). + cardinal String? + + /// Section parente (e.g. Chapitre Ier BIS). + parent String? + + /// Titre de l'article + titre String + + /// Liste des alinéas composant l'article. + alineas Alinea[] + + /// Identifiant unique de référence du texte de loi associé à cet article. + texteLoiRefUid String + /// Rréférence du texte de loi associé à cet article. + texteLoiRef TexteLoi @relation(fields: [texteLoiRefUid], references: [uid]) + + @@index([texteLoiRefUid]) +} + +/// Alinéa d'un texte de loi. +model Alinea { + /// Numéro de l'alinéa. + id Int @id + + /// Hachage de l'objet. + hash String @unique + + /// Contenu de l'alinéa. + contenu String + + /// Identifiant de référence de l'article parent. + articleRefUid String + + /// Référence de l'article parent. + articleRef Article @relation(fields: [articleRefUid], references: [uid]) + + @@index([articleRefUid]) +} diff --git a/prisma/swagger/json-schema.json b/prisma/swagger/json-schema.json index 5ec258b..8693d1f 100644 --- a/prisma/swagger/json-schema.json +++ b/prisma/swagger/json-schema.json @@ -269,11 +269,32 @@ "$ref": "#/definitions/Suppleant" } }, - "paroles": { + "interventions": { "type": "array", "items": { "$ref": "#/definitions/Paragraphe" } + }, + "loisPortees": { + "type": "array", + "items": { + "$ref": "#/definitions/TexteLoi" + }, + "description": "Lois présentées au nom de cet acteur (e.g. un premier ministre)." + }, + "loisPresentees": { + "type": "array", + "items": { + "$ref": "#/definitions/TexteLoi" + }, + "description": "Lois présentées par cet acteur." + }, + "loisSignees": { + "type": "array", + "items": { + "$ref": "#/definitions/TexteLoi" + }, + "description": "Lois signées par cet acteur." } } }, @@ -585,6 +606,14 @@ }, "description": "Texte court décrivant l'objet de la réunion." }, + "nombreParticipants": { + "type": [ + "integer", + "null" + ], + "default": 0, + "description": "Nombre de participants à la réunion" + }, "actesLegislatif": { "type": "array", "items": { @@ -646,6 +675,12 @@ "items": { "$ref": "#/definitions/Amendement" } + }, + "debats": { + "type": "array", + "items": { + "$ref": "#/definitions/Debat" + } } } }, @@ -1332,12 +1367,6 @@ "null" ] }, - "documentUid": { - "type": [ - "string", - "null" - ] - }, "exposeSommaireHtml": { "type": [ "string", @@ -1367,6 +1396,16 @@ } ] }, + "dossierRef": { + "anyOf": [ + { + "$ref": "#/definitions/Dossier" + }, + { + "type": "null" + } + ] + }, "acteurRef": { "anyOf": [ { @@ -1566,14 +1605,15 @@ "legislature": { "type": "string" }, - "seanceRef": { - "type": "string" - }, "sessionRef": { "type": "string" }, "dateSeance": { - "type": "string" + "type": [ + "string", + "null" + ], + "format": "date-time" }, "dateSeanceJour": { "type": "string" @@ -1615,6 +1655,16 @@ "quantiemesSession": { "type": "string" }, + "reunionRef": { + "anyOf": [ + { + "$ref": "#/definitions/Agenda" + }, + { + "type": "null" + } + ] + }, "paragraphes": { "type": "array", "items": { @@ -1669,7 +1719,7 @@ "properties": { "hash": { "type": "string", - "description": "Hachage de l'obejt." + "description": "Hachage de l'objet." }, "adt": { "type": [ @@ -1713,12 +1763,6 @@ "null" ] }, - "mandatRef": { - "type": [ - "string", - "null" - ] - }, "idNominationOe": { "type": [ "string", @@ -1821,10 +1865,7 @@ "null" ] }, - "debatRef": { - "$ref": "#/definitions/Debat" - }, - "acteur": { + "acteurRef": { "anyOf": [ { "$ref": "#/definitions/Acteur" @@ -1833,6 +1874,19 @@ "type": "null" } ] + }, + "mandatRef": { + "anyOf": [ + { + "$ref": "#/definitions/Mandat" + }, + { + "type": "null" + } + ] + }, + "debatRef": { + "$ref": "#/definitions/Debat" } } }, @@ -1857,13 +1911,25 @@ }, "classeCode": { "type": "string", + "enum": [ + "PRJLOI", + "PIONLOI", + "PIONRES", + "AVIS", + "MOTION", + "ALLOCUTION", + "DECLARATION", + "RAPPORT", + "RAPINF", + "RES" + ], "description": "Code unique pour traitement automatisé." }, "classeLibelle": { "type": "string", "description": "Signification du code." }, - "texteDeLoi": { + "texteLoi": { "type": [ "boolean", "null" @@ -2306,6 +2372,29 @@ "type": "string", "description": "Numéro de la législature." }, + "dateDepot": { + "type": [ + "string", + "null" + ], + "format": "date-time", + "description": "Date de dépôt du texte" + }, + "dateDernierActe": { + "type": [ + "string", + "null" + ], + "format": "date-time", + "description": "Date du dernier acte législatif lié au texte" + }, + "codeDernierActe": { + "type": [ + "string", + "null" + ], + "description": "Code du dernier acte législatif" + }, "senatChemin": { "type": [ "string", @@ -2404,6 +2493,12 @@ "$ref": "#/definitions/ActeLegislatif" } }, + "amendements": { + "type": "array", + "items": { + "$ref": "#/definitions/Amendement" + } + }, "documents": { "type": "array", "items": { @@ -3181,6 +3276,13 @@ "typeOrgane": { "type": "string" }, + "actif": { + "type": [ + "boolean", + "null" + ], + "description": "Vrai si le mandat est en cours" + }, "dateDebut": { "type": "string", "format": "date-time" @@ -3390,12 +3492,18 @@ } ] }, - "question": { + "questions": { "type": "array", "items": { "$ref": "#/definitions/Question" } }, + "interventions": { + "type": "array", + "items": { + "$ref": "#/definitions/Paragraphe" + } + }, "suppleantRef": { "anyOf": [ { @@ -3530,10 +3638,17 @@ }, "nombreReunionsAnnuelles": { "type": [ - "string", + "integer", "null" ] }, + "nombreMembres": { + "type": [ + "integer", + "null" + ], + "default": 0 + }, "positionPolitique": { "type": [ "string", @@ -3702,6 +3817,12 @@ "items": { "$ref": "#/definitions/Commune" } + }, + "textesLoi": { + "type": "array", + "items": { + "$ref": "#/definitions/TexteLoi" + } } } }, @@ -4171,7 +4292,10 @@ "description": "Hachage de l'objet" }, "positionVote": { - "type": "string", + "type": [ + "string", + "null" + ], "enum": [ "pour", "contre", @@ -4317,6 +4441,237 @@ ] } } + }, + "TexteLoi": { + "type": "object", + "properties": { + "uid": { + "type": "string", + "description": "Identifiant unique." + }, + "hash": { + "type": "string", + "description": "Hachage de l'objet" + }, + "titre": { + "type": "string", + "description": "Titre du texte de loi" + }, + "chambre": { + "type": [ + "string", + "null" + ], + "description": "Chambre du parlementaire (assemblée ou sénat)" + }, + "legislature": { + "type": "string", + "description": "Numéro de législature." + }, + "procedureAcceleree": { + "type": "boolean", + "default": false, + "description": "`true` si la procédure est accélérée ; `false` sinon." + }, + "dateConstitution": { + "type": [ + "string", + "null" + ], + "format": "date-time", + "description": "Date de la constitution associée." + }, + "dateDepot": { + "type": [ + "string", + "null" + ], + "format": "date-time", + "description": "Date de dépôt à l'Assemblée Nationale" + }, + "numero": { + "type": "string", + "description": "Numéro du texte" + }, + "commission": { + "$ref": "#/definitions/Organe" + }, + "presenteeAuNomDe": { + "type": "array", + "items": { + "$ref": "#/definitions/Acteur" + }, + "description": "Texte de loi présenté au nom de... (e.g. nom du Premier ministre)" + }, + "presenteePar": { + "type": "array", + "items": { + "$ref": "#/definitions/Acteur" + }, + "description": "Texte de loi présenté par un ensemble de députés." + }, + "signataires": { + "type": "array", + "items": { + "$ref": "#/definitions/Acteur" + }, + "description": "Signataires de cette loi." + }, + "sommaire": { + "type": "array", + "items": { + "$ref": "#/definitions/SommaireLoi" + }, + "description": "Sommaire du texte de loi." + }, + "exposeMotifsCitation": { + "type": [ + "string", + "null" + ], + "description": "Citation de l'exposé des motifs, si elle existe." + }, + "exposeMotifsDescriptionArticles": { + "type": [ + "string", + "null" + ], + "description": "Description des articles de l'exposé des motifs, si elle existe." + }, + "exposeMotifsContenu": { + "type": [ + "string", + "null" + ], + "description": "Contenu de l'exposé des motifs comprenant la description des articles." + }, + "articles": { + "type": "array", + "items": { + "$ref": "#/definitions/Article" + }, + "description": "Liste des articles du texte de loi." + } + } + }, + "SommaireLoi": { + "type": "object", + "properties": { + "uid": { + "type": "string", + "description": "Identifiant unique d'un sommaire." + }, + "hash": { + "type": "string", + "description": "Hachage de l'objet." + }, + "division": { + "type": "string", + "enum": [ + "Titre", + "Chapitre", + "Section", + "SousSection" + ] + }, + "numeroDivision": { + "type": "integer", + "description": "Numéro de la division." + }, + "sequence": { + "type": "string", + "description": "Ordre de la division dans le document." + }, + "titre": { + "type": "string", + "description": "Titre de la division." + }, + "parent": { + "type": [ + "string", + "null" + ], + "description": "Identifiant de la division parente." + }, + "texteLoiRef": { + "$ref": "#/definitions/TexteLoi" + } + } + }, + "Article": { + "type": "object", + "properties": { + "uid": { + "type": "string", + "description": "Identifiant unique d'un article." + }, + "hash": { + "type": "string", + "description": "Hachage de l'objet." + }, + "numero": { + "type": [ + "integer", + "null" + ], + "description": "Numéro de l'article." + }, + "numeros": { + "type": "array", + "items": { + "type": "integer" + }, + "description": "Numéro des articles (dans de rare cas, il y a un groupement d'articles)." + }, + "cardinal": { + "type": [ + "string", + "null" + ], + "description": "Cardinal de l'article (e.g. er, bis)." + }, + "parent": { + "type": [ + "string", + "null" + ], + "description": "Section parente (e.g. Chapitre Ier BIS)." + }, + "titre": { + "type": "string", + "description": "Titre de l'article" + }, + "alineas": { + "type": "array", + "items": { + "$ref": "#/definitions/Alinea" + }, + "description": "Liste des alinéas composant l'article." + }, + "texteLoiRef": { + "$ref": "#/definitions/TexteLoi" + } + } + }, + "Alinea": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "Numéro de l'alinéa." + }, + "hash": { + "type": "string", + "description": "Hachage de l'objet." + }, + "contenu": { + "type": "string", + "description": "Contenu de l'alinéa." + }, + "articleRef": { + "$ref": "#/definitions/Article" + } + } } }, "type": "object", @@ -4434,6 +4789,18 @@ }, "dysfonctionnement": { "$ref": "#/definitions/Dysfonctionnement" + }, + "texteLoi": { + "$ref": "#/definitions/TexteLoi" + }, + "sommaireLoi": { + "$ref": "#/definitions/SommaireLoi" + }, + "article": { + "$ref": "#/definitions/Article" + }, + "alinea": { + "$ref": "#/definitions/Alinea" } } } \ No newline at end of file