@tricoteuses/senat 3.1.10 → 3.1.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/lib/src/config.d.ts +43 -0
  2. package/lib/src/config.js +37 -0
  3. package/lib/src/conversion_textes.d.ts +11 -0
  4. package/lib/src/conversion_textes.js +320 -0
  5. package/lib/src/databases_postgres.d.ts +4 -0
  6. package/lib/src/databases_postgres.js +23 -0
  7. package/lib/src/datasets.d.ts +38 -0
  8. package/lib/src/datasets.js +247 -0
  9. package/lib/src/git.d.ts +27 -0
  10. package/lib/src/git.js +251 -0
  11. package/lib/src/loaders.d.ts +52 -0
  12. package/lib/src/loaders.js +260 -0
  13. package/lib/src/model/agenda.d.ts +6 -0
  14. package/lib/src/model/agenda.js +148 -0
  15. package/lib/src/model/ameli.d.ts +67 -0
  16. package/lib/src/model/ameli.js +150 -0
  17. package/lib/src/model/commission.d.ts +19 -0
  18. package/lib/src/model/commission.js +269 -0
  19. package/lib/src/model/debats.d.ts +39 -0
  20. package/lib/src/model/debats.js +112 -0
  21. package/lib/src/model/documents.d.ts +32 -0
  22. package/lib/src/model/documents.js +182 -0
  23. package/lib/src/model/dosleg.d.ts +144 -0
  24. package/lib/src/model/dosleg.js +468 -0
  25. package/lib/src/model/index.d.ts +7 -0
  26. package/lib/src/model/index.js +7 -0
  27. package/lib/src/model/questions.d.ts +54 -0
  28. package/lib/src/model/questions.js +91 -0
  29. package/lib/src/model/scrutins.d.ts +48 -0
  30. package/lib/src/model/scrutins.js +121 -0
  31. package/lib/src/model/seance.d.ts +3 -0
  32. package/lib/src/model/seance.js +267 -0
  33. package/lib/src/model/sens.d.ts +112 -0
  34. package/lib/src/model/sens.js +385 -0
  35. package/lib/src/model/util.d.ts +1 -0
  36. package/lib/src/model/util.js +15 -0
  37. package/lib/src/raw_types/ameli.d.ts +1762 -0
  38. package/lib/src/raw_types/ameli.js +1074 -0
  39. package/lib/src/raw_types/debats.d.ts +380 -0
  40. package/lib/src/raw_types/debats.js +266 -0
  41. package/lib/src/raw_types/dosleg.d.ts +2954 -0
  42. package/lib/src/raw_types/dosleg.js +2005 -0
  43. package/lib/src/raw_types/questions.d.ts +699 -0
  44. package/lib/src/raw_types/questions.js +493 -0
  45. package/lib/src/raw_types/sens.d.ts +7843 -0
  46. package/lib/src/raw_types/sens.js +4691 -0
  47. package/lib/src/raw_types_schemats/ameli.d.ts +541 -0
  48. package/lib/src/raw_types_schemats/ameli.js +2 -0
  49. package/lib/src/raw_types_schemats/debats.d.ts +127 -0
  50. package/lib/src/raw_types_schemats/debats.js +2 -0
  51. package/lib/src/raw_types_schemats/dosleg.d.ts +977 -0
  52. package/lib/src/raw_types_schemats/dosleg.js +2 -0
  53. package/lib/src/raw_types_schemats/questions.d.ts +237 -0
  54. package/lib/src/raw_types_schemats/questions.js +2 -0
  55. package/lib/src/raw_types_schemats/sens.d.ts +2709 -0
  56. package/lib/src/raw_types_schemats/sens.js +2 -0
  57. package/lib/src/rich_types/dosleg.d.ts +74 -0
  58. package/lib/src/rich_types/dosleg.js +34 -14
  59. package/lib/src/scripts/debug_dosleg_query.d.ts +6 -0
  60. package/lib/src/scripts/debug_dosleg_query.js +50 -0
  61. package/lib/src/scripts/retrieve_agenda.js +6 -6
  62. package/lib/src/server/dosleg.js +170 -3
  63. package/lib/src/types/agenda.d.ts +45 -0
  64. package/lib/src/types/agenda.js +1 -0
  65. package/lib/src/types/ameli.d.ts +5 -0
  66. package/lib/src/types/ameli.js +1 -0
  67. package/lib/src/types/compte_rendu.d.ts +83 -0
  68. package/lib/src/types/compte_rendu.js +1 -0
  69. package/lib/src/types/debats.d.ts +2 -0
  70. package/lib/src/types/debats.js +1 -0
  71. package/lib/src/types/dosleg.d.ts +70 -0
  72. package/lib/src/types/dosleg.js +1 -0
  73. package/lib/src/types/questions.d.ts +2 -0
  74. package/lib/src/types/questions.js +1 -0
  75. package/lib/src/types/sens.d.ts +8 -0
  76. package/lib/src/types/sens.js +1 -0
  77. package/lib/src/types/sessions.d.ts +6 -0
  78. package/lib/src/types/sessions.js +19 -0
  79. package/lib/src/types/texte.d.ts +72 -0
  80. package/lib/src/types/texte.js +15 -0
  81. package/lib/src/utils/reunion_odj_building.d.ts +7 -1
  82. package/lib/src/utils/reunion_odj_building.js +144 -21
  83. package/lib/src/utils/reunion_parsing.d.ts +3 -2
  84. package/lib/src/utils/reunion_parsing.js +4 -4
  85. package/lib/src/validators/config.d.ts +9 -0
  86. package/lib/src/validators/config.js +10 -0
  87. package/package.json +1 -1
@@ -0,0 +1,2 @@
1
+ /* tslint:disable */
2
+ export {};
@@ -19,51 +19,124 @@ export type DossierDocumentAnnexeRow = {
19
19
  };
20
20
  export type DossierTexte = {
21
21
  auteurs?: DossierAuteurRow[] | null;
22
+ avis_conseil_etat?: string | null;
22
23
  code_adoption?: string | null;
23
24
  code_organisme?: string | null;
24
25
  date?: string | null;
26
+ date_rejet_discussion_immediate?: string | null;
27
+ date_seance_rattachement?: string | null;
25
28
  id?: string | null;
29
+ libelle_url_2?: string | null;
30
+ libelle_url_3?: string | null;
31
+ libelle_url_4?: string | null;
26
32
  modification?: string | null;
27
33
  numero?: number | string | null;
34
+ numero_bis?: string | null;
28
35
  ordre_origine?: string | null;
29
36
  origine?: string | null;
37
+ prix?: string | null;
38
+ reserve_commission_speciale?: string | null;
30
39
  session?: number | null;
31
40
  titre?: string | null;
32
41
  type?: string | null;
33
42
  url?: string | null;
43
+ url_2?: string | null;
44
+ url_3?: string | null;
45
+ url_4?: string | null;
46
+ url_cnen?: string | null;
34
47
  };
35
48
  export type DossierRapport = {
49
+ annexe?: number | null;
36
50
  auteurs?: DossierAuteurRow[] | null;
51
+ bleu_budgetaire?: string | null;
37
52
  code_organisme?: string | null;
38
53
  date?: string | null;
54
+ date_seance_rattachement?: string | null;
55
+ depot_only?: string | null;
39
56
  documents_annexes?: DossierDocumentAnnexeRow[] | null;
57
+ fascicule?: number | null;
58
+ format_publication?: string | null;
40
59
  id?: string | null;
60
+ libelle_url_2?: string | null;
61
+ libelle_url_3?: string | null;
62
+ libelle_url_4?: string | null;
41
63
  numero?: number | string | null;
64
+ numero_assemblee_nationale?: string | null;
65
+ numero_bis?: string | null;
66
+ ordre_rapport?: string | null;
67
+ prix?: string | null;
68
+ resume?: string | null;
42
69
  session?: number | null;
43
70
  sous_titre?: string | null;
44
71
  titre?: string | null;
72
+ titre_court?: string | null;
73
+ tome?: number | null;
45
74
  type?: string | null;
46
75
  url?: string | null;
76
+ url_2?: string | null;
77
+ url_3?: string | null;
78
+ url_4?: string | null;
79
+ volume?: number | null;
47
80
  };
48
81
  export type DossierDateSeance = {
82
+ code?: string | null;
49
83
  date?: string | null;
84
+ statut?: string | null;
85
+ };
86
+ export type DossierReunionCommission = {
87
+ date: string | null;
88
+ titre: string | null;
89
+ url_compte_rendu: string | null;
90
+ };
91
+ export type DossierCommissionSaisie = {
92
+ code_organisme: string | null;
93
+ deleguee_au_fond: string | null;
94
+ libelle_organisme: string | null;
95
+ reunions?: DossierReunionCommission[] | null;
96
+ type_saisine: "avis" | "fond";
50
97
  };
51
98
  export type DossierLectureAssemblee = {
99
+ alias_ppre?: string | null;
52
100
  assemblee?: string | null;
53
101
  code_organisme?: string | null;
102
+ complement_numero_petite_loi?: string | null;
103
+ complement_numero_petite_loi_2?: string | null;
104
+ complement_numero_petite_loi_3?: string | null;
105
+ date_liasse_amendements_adoptes_commission?: string | null;
106
+ date_liasse_amendements_adoptes_seance?: string | null;
54
107
  date_publication_amendements_commission?: string | null;
55
108
  date_publication_amendements_seance?: string | null;
56
109
  dates_seances?: DossierDateSeance[] | null;
110
+ commissions_saisies?: DossierCommissionSaisie[] | null;
111
+ depot_only?: string | null;
57
112
  libelle_organisme?: string | null;
113
+ libelle_ppre?: string | null;
58
114
  loi_intitule_modifie?: string | null;
115
+ note_petite_loi?: string | null;
116
+ note_petite_loi_2?: string | null;
117
+ note_petite_loi_3?: string | null;
118
+ numero_liasse_amendements_adoptes_commission?: string | null;
119
+ numero_liasse_amendements_adoptes_seance?: string | null;
59
120
  numero_petite_loi?: number | null;
121
+ numero_petite_loi_commission?: number | null;
122
+ numero_texte_amende_commission?: string | null;
123
+ numero_texte_amende_seance?: string | null;
60
124
  ordre_lecture_assemblee?: string | null;
61
125
  origine_proposition?: string | null;
62
126
  rapports?: DossierRapport[] | null;
127
+ reunion_commission_ppre?: string | null;
63
128
  session?: number | null;
129
+ session_liasse_amendements_adoptes_commission?: number | null;
130
+ session_liasse_amendements_adoptes_seance?: number | null;
131
+ session_ppre?: string | null;
132
+ session_texte_amende_commission?: number | null;
133
+ session_texte_amende_seance?: number | null;
64
134
  textes?: DossierTexte[] | null;
65
135
  url_cr_debats?: string | null;
66
136
  url_petite_loi?: string | null;
137
+ url_petite_loi_2?: string | null;
138
+ url_petite_loi_3?: string | null;
139
+ url_petite_loi_commission?: string | null;
67
140
  };
68
141
  export type DossierLecture = {
69
142
  lectures_assemblee?: DossierLectureAssemblee[] | null;
@@ -138,6 +211,7 @@ export type ActeLegislatif = {
138
211
  numero_JO?: string | number | null;
139
212
  session?: number | null;
140
213
  signet_dossier: string;
214
+ rapport_url?: string | null;
141
215
  texte_url?: string | null;
142
216
  uid: string;
143
217
  url_legifrance?: string | null;
@@ -105,21 +105,39 @@ export function buildActesLegislatifs(dossier) {
105
105
  });
106
106
  }
107
107
  const rapports = lecAss.rapports ?? [];
108
- for (const rap of rapports) {
109
- if (rap.date) {
110
- const codeActeCommission = getCommissionCodeActe(phasePrefix, rap.type);
108
+ const commissionsSaisies = lecAss.commissions_saisies ?? [];
109
+ for (const commission of commissionsSaisies) {
110
+ const isAvis = commission.type_saisine === "avis";
111
+ const commissionCodeActe = isAvis
112
+ ? commission.deleguee_au_fond === "O"
113
+ ? `${phasePrefix}-COM-CAE-DEC`
114
+ : `${phasePrefix}-COM-AVIS`
115
+ : `${phasePrefix}-COM-FOND`;
116
+ const commissionRaps = rapports.filter((r) => r.code_organisme === commission.code_organisme);
117
+ const firstRapDate = commissionRaps.find((r) => r.date)?.date;
118
+ const firstReunionDate = commission.reunions?.find((r) => r.date)?.date;
119
+ const acteDate = firstRapDate ?? firstReunionDate;
120
+ if (acteDate) {
121
+ const rap = commissionRaps.find((r) => r.date);
111
122
  actes.push({
112
- code_acte: codeActeCommission,
113
- date: rap.date,
114
- libelle: `Rapport n°${rap.numero} de la commission`,
115
- id: rap.id,
116
- numero: rap.numero,
117
- code_organisme: rap.code_organisme ?? null,
118
- uid: `${loiSignet}-${phasePrefix}-COM`,
123
+ code_acte: commissionCodeActe,
124
+ date: acteDate,
125
+ libelle: isAvis
126
+ ? rap
127
+ ? `Avis n°${rap.numero} de la commission`
128
+ : "Travaux de la commission saisie pour avis"
129
+ : rap
130
+ ? `Rapport n°${rap.numero} de la commission`
131
+ : "Travaux de la commission saisie au fond",
132
+ id: rap?.id ?? null,
133
+ numero: rap?.numero ?? null,
134
+ code_organisme: commission.code_organisme ?? null,
135
+ uid: `${loiSignet}-${phasePrefix}-COM-${commission.code_organisme ?? ""}`,
119
136
  session: lecAss.session,
120
137
  chambre: "SN",
121
138
  signet_dossier: loiSignet,
122
- texte_url: rap.url,
139
+ rapport_url: rap?.url ?? null,
140
+ texte_url: depotTexte?.url ?? null,
123
141
  });
124
142
  }
125
143
  }
@@ -128,6 +146,7 @@ export function buildActesLegislatifs(dossier) {
128
146
  datesSeances.sort(compareByDate);
129
147
  const premiereSeance = datesSeances[0];
130
148
  if (premiereSeance && premiereSeance.date) {
149
+ const texteAvantSeance = textesTries.find((t) => (t.origine || "").toLowerCase().includes("de la commission"));
131
150
  actes.push({
132
151
  code_acte: `${phasePrefix}-DEBATS-SEANCE`,
133
152
  date: premiereSeance.date,
@@ -138,11 +157,14 @@ export function buildActesLegislatifs(dossier) {
138
157
  chambre: "SN",
139
158
  signet_dossier: loiSignet,
140
159
  code_organisme: null,
160
+ texte_url: texteAvantSeance?.url ?? null,
141
161
  });
142
162
  }
143
163
  }
144
164
  const texteFinal = [...textesTries].reverse().find((t) => {
145
165
  const origine = (t.origine || "").toLowerCase();
166
+ if (origine.includes("de la commission"))
167
+ return false;
146
168
  return (origine.includes("adopté") ||
147
169
  origine.includes("rejeté") ||
148
170
  origine.includes("devenu résolution") ||
@@ -157,9 +179,7 @@ export function buildActesLegislatifs(dossier) {
157
179
  else if (origine.includes("devenue résolution")) {
158
180
  libelleStatut = "Adopté";
159
181
  }
160
- // "devenu résolution du Sénat" : adoptée en commission sans séance publique (art. 73 quinquies RSN)
161
- // On utilise COM-CAE-DEC plutôt que DEBATS-DEC pour refléter l'absence de séance plénière
162
- const codeActeDecision = (texteFinal.origine || "").toLowerCase().includes("devenu résolution")
182
+ const codeActeDecision = origine.includes("devenu résolution")
163
183
  ? `${phasePrefix}-COM-CAE-DEC`
164
184
  : `${phasePrefix}-DEBATS-DEC`;
165
185
  actes.push({
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Debug script to check the DosLeg query compilation
4
+ * Helps identify the "column undefined" error
5
+ */
6
+ export {};
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Debug script to check the DosLeg query compilation
4
+ * Helps identify the "column undefined" error
5
+ */
6
+ import { db } from "../server/databases_postgres.js";
7
+ import { jsonArrayFrom } from "kysely/helpers/postgres";
8
+ import { sql } from "kysely";
9
+ async function debugDoslegQuery() {
10
+ console.log("=== Debugging DosLeg Query ===\n");
11
+ try {
12
+ // Build the same query as findAllDossiers but capture SQL
13
+ const query = db
14
+ .withSchema("senat")
15
+ .selectFrom("dosleg_loi as loi")
16
+ .leftJoin("dosleg_typloi as typloi", "typloi.typloicod", "loi.typloicod")
17
+ .leftJoin("dosleg_etaloi as etaloi", "etaloi.etaloicod", "loi.etaloicod")
18
+ .leftJoin("dosleg_deccoc as deccoc", "deccoc.deccoccod", "loi.deccoccod")
19
+ .select((eb) => [
20
+ sql `rtrim(${eb.ref("loi.loicod")})`.as("code"),
21
+ "loi.numero as numero",
22
+ "loi.signet as signet",
23
+ ]);
24
+ const compiled = query.compile();
25
+ console.log("✓ Query compiled successfully (basic columns)\n");
26
+ console.log("SQL:", compiled.sql);
27
+ console.log("\n");
28
+ // Try with simple lectures first
29
+ const queryWithLectures = db
30
+ .withSchema("senat")
31
+ .selectFrom("dosleg_loi as loi")
32
+ .select((eb) => [
33
+ "loi.signet as signet",
34
+ jsonArrayFrom(eb.withSchema("senat").selectFrom("dosleg_lecture as lecture").select(["lecture.lecidt as id"])).as("lectures"),
35
+ ]);
36
+ const compiledWithLectures = queryWithLectures.compile();
37
+ console.log("✓ Query with simple lectures compiled successfully\n");
38
+ console.log("SQL:", compiledWithLectures.sql);
39
+ console.log("\n");
40
+ console.log("✅ Basic query structures seem valid");
41
+ console.log("\nThe issue is likely in one of the nested subqueries with cross-references.");
42
+ console.log("Try running findAllDossiers with the verbose flag to see exactly where it fails.");
43
+ }
44
+ catch (error) {
45
+ console.error("❌ Error during query compilation:");
46
+ console.error(error instanceof Error ? error.message : String(error));
47
+ process.exit(1);
48
+ }
49
+ }
50
+ debugDoslegQuery().catch(console.error);
@@ -10,7 +10,7 @@ import { ID_DATE_FORMAT } from "./datautil.js";
10
10
  import { assertExistingDirectory, commonOptions } from "./shared/cli_helpers.js";
11
11
  import { fetchWithRetry } from "./shared/util.js";
12
12
  import { buildReunionsByBucket } from "../utils/reunion_parsing.js";
13
- import { buildSenatDossierIndex } from "../utils/reunion_odj_building.js";
13
+ import { buildSenatDossierIndex, buildDoslegReunionIndex } from "../utils/reunion_odj_building.js";
14
14
  const optionsDefinitions = [
15
15
  ...commonOptions,
16
16
  {
@@ -47,8 +47,8 @@ async function retrieveAgendas(options, sessions) {
47
47
  if (options["parseAgenda"]) {
48
48
  fs.ensureDirSync(transformedAgendaDir);
49
49
  }
50
- let dossierIndex = {};
51
- dossierIndex = buildSenatDossierIndex(options);
50
+ const dossierIndex = buildSenatDossierIndex(options);
51
+ const doslegReunionIndex = buildDoslegReunionIndex(options);
52
52
  for (const session of sessions) {
53
53
  const originalAgendaSessionDir = path.join(originalAgendaDir, `${session}`);
54
54
  fs.ensureDirSync(originalAgendaSessionDir);
@@ -68,7 +68,7 @@ async function retrieveAgendas(options, sessions) {
68
68
  try {
69
69
  await downloadAgenda(agendaName, agendaPath);
70
70
  if (options["parseAgenda"]) {
71
- await parseAgenda(transformedAgendaSessionDir, agendaFileName, agendaPath, dossierIndex);
71
+ await parseAgenda(transformedAgendaSessionDir, agendaFileName, agendaPath, dossierIndex, doslegReunionIndex);
72
72
  }
73
73
  }
74
74
  catch (error) {
@@ -104,7 +104,7 @@ function writeGroupsAsFiles(dir, groups) {
104
104
  fs.writeJSONSync(outPath, g, { spaces: 2 });
105
105
  }
106
106
  }
107
- async function parseAgenda(transformedAgendaSessionDir, agendaFileName, agendaPath, dossierBySenatUrl) {
107
+ async function parseAgenda(transformedAgendaSessionDir, agendaFileName, agendaPath, dossierBySenatUrl, doslegReunionIndex) {
108
108
  if (!options["silent"])
109
109
  console.log(`Parsing Agenda ${agendaPath}…`);
110
110
  const parsedAgendaEvents = await parseAgendaFromFile(agendaPath);
@@ -112,7 +112,7 @@ async function parseAgenda(transformedAgendaSessionDir, agendaFileName, agendaPa
112
112
  return;
113
113
  const flatPath = path.join(transformedAgendaSessionDir, `${agendaFileName}.json`);
114
114
  fs.writeJSONSync(flatPath, parsedAgendaEvents, { spaces: 2 });
115
- const byBucket = buildReunionsByBucket(parsedAgendaEvents, dossierBySenatUrl);
115
+ const byBucket = buildReunionsByBucket(parsedAgendaEvents, dossierBySenatUrl, doslegReunionIndex);
116
116
  // SP
117
117
  if (byBucket.IDS.length > 0) {
118
118
  writeGroupsAsFiles(transformedAgendaSessionDir, byBucket.IDS);
@@ -87,6 +87,31 @@ export async function* findAllDossiers() {
87
87
  "lecass.debatsurl as url_cr_debats",
88
88
  sql `to_char(lecass.lecassamecomdat, 'YYYY-MM-DD')`.as("date_publication_amendements_commission"),
89
89
  sql `to_char(lecass.lecassamedat, 'YYYY-MM-DD')`.as("date_publication_amendements_seance"),
90
+ "lecass.ptlnumcpl as complement_numero_petite_loi",
91
+ "lecass.ptlnot as note_petite_loi",
92
+ "lecass.ptlurl2 as url_petite_loi_2",
93
+ "lecass.ptlnot2 as note_petite_loi_2",
94
+ "lecass.ptlurl3 as url_petite_loi_3",
95
+ "lecass.ptlnot3 as note_petite_loi_3",
96
+ "lecass.ptlnumcpl2 as complement_numero_petite_loi_2",
97
+ "lecass.ptlnumcpl3 as complement_numero_petite_loi_3",
98
+ "lecass.libppr as libelle_ppre",
99
+ "lecass.sesppr as session_ppre",
100
+ "lecass.aliasppr as alias_ppre",
101
+ "lecass.ptlurlcom as url_petite_loi_commission",
102
+ "lecass.ptlnumcom as numero_petite_loi_commission",
103
+ "lecass.lecassame as numero_texte_amende_seance",
104
+ sql `lecass.lecassameses::int`.as("session_texte_amende_seance"),
105
+ "lecass.lecassamecom as numero_texte_amende_commission",
106
+ sql `lecass.lecassamesescom::int`.as("session_texte_amende_commission"),
107
+ "lecass.reucom as reunion_commission_ppre",
108
+ "lecass.depot_only as depot_only",
109
+ "lecass.lecassameado as numero_liasse_amendements_adoptes_seance",
110
+ sql `to_char(lecass.lecassameadodat, 'YYYY-MM-DD')`.as("date_liasse_amendements_adoptes_seance"),
111
+ sql `lecass.lecassameadoses::int`.as("session_liasse_amendements_adoptes_seance"),
112
+ "lecass.lecassamecomado as numero_liasse_amendements_adoptes_commission",
113
+ sql `to_char(lecass.lecassamecomadodat, 'YYYY-MM-DD')`.as("date_liasse_amendements_adoptes_commission"),
114
+ sql `lecass.lecassamecomadoses::int`.as("session_liasse_amendements_adoptes_commission"),
90
115
  // Textes
91
116
  jsonArrayFrom(eb3
92
117
  .withSchema("senat")
@@ -118,6 +143,19 @@ export async function* findAllDossiers() {
118
143
  sql `rtrim(typtxt.typtxtlib)`.as("type"),
119
144
  sql `to_char(texte.txtoritxtdat, 'YYYY-MM-DD')`.as("date"),
120
145
  sql `texte.sesann::int`.as("session"),
146
+ "texte.url2 as url_2",
147
+ "texte.url2txt as libelle_url_2",
148
+ "texte.url3 as url_3",
149
+ "texte.url3txt as libelle_url_3",
150
+ "texte.url4 as url_4",
151
+ "texte.url4txt as libelle_url_4",
152
+ "texte.numerobis as numero_bis",
153
+ "texte.texace as avis_conseil_etat",
154
+ "texte.url_cnen as url_cnen",
155
+ "texte.reserve_comspe as reserve_commission_speciale",
156
+ sql `to_char(texte.datrejet_disc_immediate, 'YYYY-MM-DD')`.as("date_rejet_discussion_immediate"),
157
+ sql `to_char(texte.texdatsea, 'YYYY-MM-DD')`.as("date_seance_rattachement"),
158
+ "texte.prix as prix",
121
159
  // Auteurs du texte
122
160
  jsonArrayFrom(eb4
123
161
  .withSchema("senat")
@@ -168,6 +206,26 @@ export async function* findAllDossiers() {
168
206
  sql `rtrim(rtrim(rap.rapsoustit))`.as("sous_titre"),
169
207
  sql `to_char(rap.date_depot, 'YYYY-MM-DD')`.as("date"),
170
208
  sql `rap.sesann::int`.as("session"),
209
+ "rap.raptom as tome",
210
+ "rap.rapfac as fascicule",
211
+ "rap.rapann as annexe",
212
+ "rap.rapvol as volume",
213
+ "rap.raptitcou as titre_court",
214
+ "rap.url2 as url_2",
215
+ "rap.url2txt as libelle_url_2",
216
+ "rap.url3 as url_3",
217
+ "rap.url3txt as libelle_url_3",
218
+ "rap.url4 as url_4",
219
+ "rap.url4txt as libelle_url_4",
220
+ "rap.prix as prix",
221
+ "rap.rapnuman as numero_assemblee_nationale",
222
+ "rap.numerobis as numero_bis",
223
+ sql `to_char(rap.rapdatsea, 'YYYY-MM-DD')`.as("date_seance_rattachement"),
224
+ "rap.depot_only as depot_only",
225
+ "rap.rapres as resume",
226
+ "rap.forpubcod as code_format_publication",
227
+ "rap.blecod as code_bleu_budgetaire",
228
+ "lecassrap.lecassrapord as ordre_rapport",
171
229
  // Auteurs du rapport
172
230
  jsonArrayFrom(eb4
173
231
  .withSchema("senat")
@@ -197,14 +255,54 @@ export async function* findAllDossiers() {
197
255
  jsonArrayFrom(eb3
198
256
  .withSchema("senat")
199
257
  .selectFrom("dosleg_date_seance as date_seance")
200
- .select([sql `to_char(date_seance.date_s, 'YYYY-MM-DD')`.as("date")])
258
+ .select([
259
+ "date_seance.code as code",
260
+ sql `to_char(date_seance.date_s, 'YYYY-MM-DD')`.as("date"),
261
+ "date_seance.statut as statut",
262
+ ])
201
263
  .whereRef("date_seance.lecidt", "=", "lecass.lecassidt")).as("dates_seances"),
264
+ // Commissions saisies (source : ameli.sai)
265
+ // Fusionnées avec la commission au fond (lecass.orgcod) en post-traitement
266
+ jsonArrayFrom(eb3
267
+ .withSchema("senat")
268
+ .selectFrom("ameli_sai as sai")
269
+ .innerJoin("ameli_txt_ameli as txt_a", "txt_a.id", "sai.txtid")
270
+ .innerJoin("ameli_com_ameli as com_a", "com_a.entid", "sai.comid")
271
+ .innerJoin("ameli_ses as ses_a", "ses_a.id", "sai.sesid")
272
+ .select([
273
+ sql `rtrim(com_a.lib)`.as("code_organisme"),
274
+ sql `rtrim(com_a.lil)`.as("libelle_organisme"),
275
+ sql `case when sai.saityp = 'A' then 'avis' else 'fond' end`.as("type_saisine"),
276
+ sql `sai.isdelegfond`.as("deleguee_au_fond"),
277
+ ])
278
+ .where("sai.saityp", "in", ["A", "F"])
279
+ .where("txt_a.doslegsignet", "is not", null)
280
+ // correlated sub-query references outer tables not in FROM clause
281
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
282
+ .where(sql `txt_a.doslegsignet = loi.signet`)
283
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
284
+ .where(sql `ses_a.ann = lecass.sesann`)
285
+ .groupBy(["com_a.lib", "com_a.lil", "sai.saityp", "sai.isdelegfond"])).as("commissions_saisies_ameli"),
286
+ // Réunions de commission (source : dosleg_aud)
287
+ jsonArrayFrom(eb3
288
+ .withSchema("senat")
289
+ .selectFrom("dosleg_aud as aud")
290
+ .innerJoin("dosleg_org as org_a", "org_a.orgcod", "aud.orgcod")
291
+ .select([
292
+ sql `rtrim(aud.orgcod)`.as("code_organisme"),
293
+ sql `rtrim(org_a.orgnom)`.as("libelle_organisme"),
294
+ sql `to_char(aud.auddat, 'YYYY-MM-DD')`.as("date"),
295
+ sql `rtrim(aud.audtit)`.as("titre"),
296
+ sql `case when aud.audurl like 'http%' then rtrim(aud.audurl) else 'https://www.senat.fr/' || rtrim(aud.audurl) end`.as("url_compte_rendu"),
297
+ ])
298
+ .whereRef("aud.lecassidt", "=", "lecass.lecassidt")
299
+ .orderBy("aud.auddat", "asc")).as("reunions_commission"),
202
300
  ])
203
301
  .whereRef("lecass.lecidt", "=", "lecture.lecidt")
204
302
  .orderBy("lecass.ordreass", "asc")).as("lectures_assemblee"),
205
303
  ])
206
304
  .whereRef("lecture.loicod", "=", "loi.loicod")
207
- .orderBy("typlec.typlecord", "asc")).as("lectures"),
305
+ .orderBy(sql `COALESCE(typlec.typlecord::int, 9999)`, "asc")).as("lectures"),
208
306
  // Thèmes
209
307
  jsonArrayFrom(eb
210
308
  .withSchema("senat")
@@ -221,8 +319,77 @@ export async function* findAllDossiers() {
221
319
  yield {
222
320
  ...row,
223
321
  signet: row.signet,
224
- lectures: row.lectures ?? [],
322
+ lectures: mergeCommissionsSaisies(row.lectures ?? []),
225
323
  themes: row.themes ?? [],
226
324
  };
227
325
  }
228
326
  }
327
+ function mergeCommissionsSaisies(lectures) {
328
+ return lectures.map((lecture) => {
329
+ const { lectures_assemblee, ...restLecture } = lecture;
330
+ if (!lectures_assemblee) {
331
+ return { ...restLecture, lectures_assemblee: undefined };
332
+ }
333
+ return {
334
+ ...restLecture,
335
+ lectures_assemblee: lectures_assemblee.map((lecAss) => {
336
+ const { commissions_saisies_ameli, reunions_commission, ...restLecAss } = lecAss;
337
+ const commissionsSaisies = [];
338
+ const hasFondFromAmeli = commissions_saisies_ameli?.some((c) => c.type_saisine === "fond");
339
+ if (!hasFondFromAmeli) {
340
+ const fondOrg = lecAss.code_organisme;
341
+ if (fondOrg) {
342
+ commissionsSaisies.push({
343
+ code_organisme: fondOrg,
344
+ libelle_organisme: lecAss.libelle_organisme ?? null,
345
+ type_saisine: "fond",
346
+ deleguee_au_fond: null,
347
+ });
348
+ }
349
+ }
350
+ if (commissions_saisies_ameli) {
351
+ for (const c of commissions_saisies_ameli) {
352
+ if (c.type_saisine === "fond" && !hasFondFromAmeli) {
353
+ continue;
354
+ }
355
+ commissionsSaisies.push({
356
+ code_organisme: c.code_organisme,
357
+ libelle_organisme: c.libelle_organisme,
358
+ type_saisine: c.type_saisine,
359
+ deleguee_au_fond: c.deleguee_au_fond,
360
+ });
361
+ }
362
+ }
363
+ const knownOrgs = new Set(commissionsSaisies.map((c) => c.code_organisme));
364
+ if (reunions_commission) {
365
+ const audOrgs = [...new Set(reunions_commission.map((r) => r.code_organisme))];
366
+ for (const audOrg of audOrgs) {
367
+ if (audOrg && !knownOrgs.has(audOrg)) {
368
+ const audLibelle = reunions_commission.find((r) => r.code_organisme === audOrg)?.libelle_organisme;
369
+ commissionsSaisies.push({
370
+ code_organisme: audOrg,
371
+ libelle_organisme: audLibelle ?? null,
372
+ type_saisine: "avis",
373
+ deleguee_au_fond: null,
374
+ });
375
+ knownOrgs.add(audOrg);
376
+ }
377
+ }
378
+ }
379
+ for (const commission of commissionsSaisies) {
380
+ commission.reunions = reunions_commission
381
+ ?.filter((r) => r.code_organisme === commission.code_organisme)
382
+ .map(({ date, titre, url_compte_rendu }) => ({
383
+ date,
384
+ titre,
385
+ url_compte_rendu,
386
+ })) ?? null;
387
+ }
388
+ return {
389
+ ...restLecAss,
390
+ commissions_saisies: commissionsSaisies,
391
+ };
392
+ }),
393
+ };
394
+ });
395
+ }
@@ -0,0 +1,45 @@
1
+ export interface AgendaEvent {
2
+ id: string;
3
+ type: string | null;
4
+ date: string;
5
+ startTime: string | null;
6
+ endTime: string | null;
7
+ timeOriginal: string | null;
8
+ titre: string;
9
+ organe: string | null;
10
+ objet: string | null;
11
+ lieu: string | null;
12
+ captationVideo: boolean;
13
+ urlDossierSenat: string | null;
14
+ quantieme: string | null;
15
+ }
16
+ export type TimeSlot = "MATIN" | "APRES-MIDI" | "SOIR" | "UNKNOWN";
17
+ export interface Reunion {
18
+ uid: string;
19
+ chambre: "SN";
20
+ date: string;
21
+ startTime: string | null;
22
+ endTime: string | null;
23
+ captationVideo: boolean;
24
+ titre: string;
25
+ type: string;
26
+ organe?: string;
27
+ objet?: string;
28
+ lieu?: string;
29
+ events: AgendaEvent[];
30
+ compteRenduRefUid?: string;
31
+ transcriptionRef?: string;
32
+ urlVideo?: string;
33
+ urlPageVideo?: string;
34
+ timecodeDebutVideo?: number;
35
+ timecodeFinVideo?: number;
36
+ odj?: ReunionOdj;
37
+ }
38
+ export interface ReunionOdjPoint {
39
+ objet: string | null;
40
+ dossierLegislatifRef: string | null;
41
+ codeEtape: string | null;
42
+ }
43
+ export interface ReunionOdj {
44
+ pointsOdj: ReunionOdjPoint[];
45
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,5 @@
1
+ import { TxtAmeli } from "../raw_types/ameli.js";
2
+ import { Sub } from "../raw_types/ameli.js";
3
+ export interface TxtAmeliCustom extends TxtAmeli {
4
+ subids?: Sub["id"][];
5
+ }
@@ -0,0 +1 @@
1
+ export {};