@tricoteuses/senat 2.7.1 → 2.8.4

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 (119) hide show
  1. package/lib/aggregates.d.ts +52 -0
  2. package/lib/aggregates.js +949 -0
  3. package/lib/aggregates.mjs +726 -0
  4. package/lib/aggregates.ts +852 -0
  5. package/lib/config.mjs +16 -0
  6. package/lib/config.ts +26 -0
  7. package/lib/databases.mjs +55 -0
  8. package/lib/databases.ts +68 -0
  9. package/lib/datasets.mjs +78 -0
  10. package/lib/datasets.ts +118 -0
  11. package/lib/fields.d.ts +10 -0
  12. package/lib/fields.js +68 -0
  13. package/lib/fields.mjs +22 -0
  14. package/lib/fields.ts +29 -0
  15. package/lib/index.mjs +7 -0
  16. package/lib/index.ts +64 -0
  17. package/lib/inserters.d.ts +98 -0
  18. package/lib/inserters.js +500 -0
  19. package/lib/inserters.mjs +360 -0
  20. package/lib/inserters.ts +521 -0
  21. package/lib/loaders.d.ts +1 -0
  22. package/lib/loaders.js +5 -0
  23. package/lib/loaders.mjs +97 -0
  24. package/lib/loaders.ts +173 -0
  25. package/lib/model/agenda.js +22 -22
  26. package/lib/model/ameli.mjs +57 -0
  27. package/lib/model/ameli.ts +86 -0
  28. package/lib/model/debats.mjs +43 -0
  29. package/lib/model/debats.ts +68 -0
  30. package/lib/model/dosleg.mjs +163 -0
  31. package/lib/model/dosleg.ts +204 -0
  32. package/lib/model/index.mjs +4 -0
  33. package/lib/model/index.ts +13 -0
  34. package/lib/model/questions.d.ts +0 -20
  35. package/lib/model/questions.js +1 -32
  36. package/lib/model/questions.mjs +76 -0
  37. package/lib/model/questions.ts +102 -0
  38. package/lib/model/sens.mjs +339 -0
  39. package/lib/model/sens.ts +432 -0
  40. package/lib/model/texte.mjs +156 -0
  41. package/lib/model/texte.ts +174 -0
  42. package/lib/raw_types/ameli.d.ts +20 -0
  43. package/lib/raw_types/questions.d.ts +4 -70
  44. package/lib/raw_types_kysely/ameli.d.ts +915 -0
  45. package/lib/raw_types_kysely/ameli.js +7 -0
  46. package/lib/raw_types_kysely/ameli.mjs +5 -0
  47. package/lib/raw_types_kysely/ameli.ts +951 -0
  48. package/lib/raw_types_kysely/debats.d.ts +207 -0
  49. package/lib/raw_types_kysely/debats.js +7 -0
  50. package/lib/raw_types_kysely/debats.mjs +5 -0
  51. package/lib/raw_types_kysely/debats.ts +222 -0
  52. package/lib/raw_types_kysely/dosleg.d.ts +3532 -0
  53. package/lib/raw_types_kysely/dosleg.js +7 -0
  54. package/lib/raw_types_kysely/dosleg.mjs +5 -0
  55. package/lib/raw_types_kysely/dosleg.ts +3621 -0
  56. package/lib/raw_types_kysely/questions.d.ts +414 -0
  57. package/lib/raw_types_kysely/questions.js +7 -0
  58. package/lib/raw_types_kysely/questions.mjs +5 -0
  59. package/lib/raw_types_kysely/questions.ts +426 -0
  60. package/lib/raw_types_kysely/sens.d.ts +4394 -0
  61. package/lib/raw_types_kysely/sens.js +7 -0
  62. package/lib/raw_types_kysely/sens.mjs +5 -0
  63. package/lib/raw_types_kysely/sens.ts +4499 -0
  64. package/lib/raw_types_schemats/ameli.mjs +2 -0
  65. package/lib/raw_types_schemats/ameli.ts +601 -0
  66. package/lib/raw_types_schemats/debats.mjs +2 -0
  67. package/lib/raw_types_schemats/debats.ts +145 -0
  68. package/lib/raw_types_schemats/dosleg.mjs +2 -0
  69. package/lib/raw_types_schemats/dosleg.ts +2193 -0
  70. package/lib/raw_types_schemats/questions.mjs +2 -0
  71. package/lib/raw_types_schemats/questions.ts +249 -0
  72. package/lib/raw_types_schemats/sens.mjs +2 -0
  73. package/lib/raw_types_schemats/sens.ts +2907 -0
  74. package/lib/scripts/convert_data.mjs +95 -0
  75. package/lib/scripts/convert_data.ts +119 -0
  76. package/lib/scripts/data-download.d.ts +1 -0
  77. package/lib/scripts/data-download.js +9 -0
  78. package/lib/scripts/datautil.mjs +16 -0
  79. package/lib/scripts/datautil.ts +19 -0
  80. package/lib/scripts/images/transparent_150x192.jpg +0 -0
  81. package/lib/scripts/images/transparent_155x225.jpg +0 -0
  82. package/lib/scripts/parse_textes.mjs +38 -0
  83. package/lib/scripts/parse_textes.ts +52 -0
  84. package/lib/scripts/retrieve_documents.mjs +243 -0
  85. package/lib/scripts/retrieve_documents.ts +279 -0
  86. package/lib/scripts/retrieve_open_data.js +11 -9
  87. package/lib/scripts/retrieve_open_data.mjs +214 -0
  88. package/lib/scripts/retrieve_open_data.ts +261 -0
  89. package/lib/scripts/retrieve_senateurs_photos.mjs +147 -0
  90. package/lib/scripts/retrieve_senateurs_photos.ts +177 -0
  91. package/lib/scripts/retrieve_textes.d.ts +1 -0
  92. package/lib/scripts/retrieve_textes.mjs +165 -0
  93. package/lib/scripts/retrieve_textes.ts +79 -0
  94. package/lib/scripts/shared/cli_helpers.ts +36 -0
  95. package/lib/scripts/shared/util.ts +33 -0
  96. package/lib/strings.mjs +18 -0
  97. package/lib/strings.ts +26 -0
  98. package/lib/types/ameli.mjs +13 -0
  99. package/lib/types/ameli.ts +21 -0
  100. package/lib/types/debats.mjs +2 -0
  101. package/lib/types/debats.ts +6 -0
  102. package/lib/types/dosleg.mjs +151 -0
  103. package/lib/types/dosleg.ts +284 -0
  104. package/lib/types/questions.mjs +1 -0
  105. package/lib/types/questions.ts +3 -0
  106. package/lib/types/sens.mjs +1 -0
  107. package/lib/types/sens.ts +12 -0
  108. package/lib/types/sessions.mjs +43 -0
  109. package/lib/types/sessions.ts +42 -0
  110. package/lib/types/texte.mjs +16 -0
  111. package/lib/types/texte.ts +66 -0
  112. package/lib/typings/windows-1252.d.js +2 -0
  113. package/lib/typings/windows-1252.d.mjs +2 -0
  114. package/lib/typings/windows-1252.d.ts +11 -0
  115. package/lib/validators/config.mjs +54 -0
  116. package/lib/validators/config.ts +79 -0
  117. package/lib/validators/senat.mjs +24 -0
  118. package/lib/validators/senat.ts +26 -0
  119. package/package.json +7 -5
package/lib/loaders.ts ADDED
@@ -0,0 +1,173 @@
1
+ import fs from "fs"
2
+ import path from "path"
3
+
4
+ import { Dataset, datasets } from "./datasets"
5
+ import { DossierLegislatifResult } from "./model/dosleg"
6
+ import { QuestionResult } from "./model/questions"
7
+ import { CirconscriptionResult, SenateurResult } from "./model/sens"
8
+ import { UNDEFINED_SESSION } from "./scripts/datautil"
9
+ import { FlatTexte } from "./types/texte"
10
+
11
+ export { EnabledDatasets } from "./datasets"
12
+
13
+ type IterItem<T> = {
14
+ item: T
15
+ filePathFromDataset?: string,
16
+ legislature?: number
17
+ }
18
+
19
+ export interface DossierLegislatifTexteResult {
20
+ signet_dossier: string,
21
+ url_dossier_senat: string,
22
+ url_dossier_assemblee_nationale: string | null,
23
+ type_lecture: string
24
+ libelle_lecture: string
25
+ libelle_organisme: string | null
26
+ numero: string | null
27
+ url: string
28
+ origine_texte: string
29
+ type_texte: string
30
+ date: Date
31
+ session: string | null
32
+ auteurs: {
33
+ prenom: string | null
34
+ nom_usuel: string
35
+ matricule: string | null
36
+ }[]
37
+ }
38
+
39
+ export function * iterFilePaths (dirPath: string): Generator<string> {
40
+ if (dirPath && fs.existsSync(dirPath)) {
41
+ const files = fs.readdirSync(dirPath, { withFileTypes: true, recursive: true })
42
+ for (const file of files) {
43
+ if (file.isFile()) {
44
+ yield path.join(file.parentPath, file.name)
45
+ }
46
+ }
47
+ }
48
+ }
49
+
50
+ function * iterLoadSenatItems<T> (
51
+ dataDir: string,
52
+ dataset: Dataset,
53
+ legislatureOrSession?: number,
54
+ subDir?: string,
55
+ { log = false } = {},
56
+ ): Generator<IterItem<T>> {
57
+ let itemsDir = path.join(dataDir, dataset.database)
58
+ if (legislatureOrSession) {
59
+ itemsDir = path.join(itemsDir, String(legislatureOrSession))
60
+ }
61
+ if (subDir) {
62
+ itemsDir = path.join(itemsDir, subDir)
63
+ }
64
+ for (const filePath of iterFilePaths(itemsDir)) {
65
+ if (log) {
66
+ console.log(`Loading file: ${filePath}…`)
67
+ }
68
+
69
+ const itemJson = fs.readFileSync(filePath, { encoding: "utf8" })
70
+ const item: T = JSON.parse(itemJson)
71
+
72
+ const filePathFromDataset = filePath.substring(filePath.indexOf(dataset.database) + dataset.database.length)
73
+
74
+ yield {
75
+ item,
76
+ filePathFromDataset,
77
+ legislature: legislatureOrSession,
78
+ }
79
+ }
80
+ }
81
+
82
+ export function * iterLoadSenatDossiersLegislatifs (
83
+ dataDir: string,
84
+ session: number | undefined,
85
+ options = {},
86
+ ): Generator<IterItem<DossierLegislatifResult>> {
87
+ for (const dossierLegislatifItem
88
+ of iterLoadSenatItems<DossierLegislatifResult>(dataDir, datasets.dosleg, session, undefined, options)
89
+ ) {
90
+ yield dossierLegislatifItem
91
+ }
92
+ }
93
+
94
+ export function * iterLoadSenatDossiersLegislatifsTextes (
95
+ dataDir: string,
96
+ session: number | undefined,
97
+ options = {},
98
+ ): Generator<IterItem<DossierLegislatifTexteResult>> {
99
+ for (const { item: dossierLegislatif } of iterLoadSenatDossiersLegislatifs(dataDir, session, options)) {
100
+ for (const lecture of dossierLegislatif.lectures) {
101
+ const lecturesSenat = lecture.lectures_assemblee
102
+ .filter(lectureAssemblee => lectureAssemblee.assemblee === "Sénat")
103
+ for (const lectureSenat of lecturesSenat) {
104
+ for (const texte of lectureSenat.textes) {
105
+ const enrichedTexte = {
106
+ signet_dossier: dossierLegislatif.signet,
107
+ url_dossier_senat: dossierLegislatif.url,
108
+ url_dossier_assemblee_nationale: dossierLegislatif.url_dossier_assemblee_nationale,
109
+ type_lecture: lecture.type_lecture,
110
+ libelle_lecture: lecture.libelle,
111
+ libelle_organisme: lectureSenat.libelle_organisme,
112
+ ...texte,
113
+ }
114
+ const texteItem: IterItem<DossierLegislatifTexteResult> = {
115
+ item: enrichedTexte,
116
+ }
117
+ if (texte.url) {
118
+ const texteName = path.parse(texte.url).name
119
+ texteItem.filePathFromDataset
120
+ = path.join(`${texte.session ?? UNDEFINED_SESSION}`, texteName, `${texteName}.pdf`)
121
+ }
122
+ yield texteItem
123
+ }
124
+ }
125
+ }
126
+ }
127
+ }
128
+
129
+ export function loadSenatTexteContent (
130
+ dataDir: string,
131
+ textePathFromDataset: string,
132
+ ): IterItem<FlatTexte | null> {
133
+ const parsedTextePath = path.parse(textePathFromDataset)
134
+ const jsonTexteName = `${parsedTextePath.name}.akn.json`
135
+ const fullTextePath = path.join(dataDir, "leg", "transformed", parsedTextePath.dir, jsonTexteName)
136
+ if (!fs.existsSync(fullTextePath)) {
137
+ return { item: null }
138
+ }
139
+ const texteJson = fs.readFileSync(fullTextePath, { encoding: "utf8" })
140
+ return { item: JSON.parse(texteJson) }
141
+ }
142
+
143
+ export function * iterLoadSenatSenateurs (
144
+ dataDir: string,
145
+ options = {},
146
+ ): Generator<IterItem<SenateurResult>> {
147
+ for (const senateurItem of iterLoadSenatItems<SenateurResult>(dataDir, datasets.sens, undefined, "sens", options)) {
148
+ yield senateurItem
149
+ }
150
+ }
151
+
152
+ export function * iterLoadSenatCirconscriptions (
153
+ dataDir: string,
154
+ options = {},
155
+ ): Generator<IterItem<CirconscriptionResult>> {
156
+ for (const circonscriptionItem
157
+ of iterLoadSenatItems<CirconscriptionResult>(dataDir, datasets.sens, undefined, "circonscriptions", options)
158
+ ) {
159
+ yield circonscriptionItem
160
+ }
161
+ }
162
+
163
+ export function * iterLoadSenatQuestions (
164
+ dataDir: string,
165
+ legislature: number,
166
+ options = {},
167
+ ): Generator<IterItem<QuestionResult>> {
168
+ for (const questionItem
169
+ of iterLoadSenatItems<QuestionResult>(dataDir, datasets.questions, legislature, undefined, options)
170
+ ) {
171
+ yield questionItem
172
+ }
173
+ }
@@ -3,6 +3,9 @@ import { DateTime } from "luxon";
3
3
  import path from "path";
4
4
  import { ID_DATE_FORMAT, STANDARD_DATE_FORMAT } from "../scripts/datautil";
5
5
  const FR_TZ = "Europe/Paris";
6
+ function eventIsSeance(eventElement) {
7
+ return eventElement.classList.contains("evt-seance");
8
+ }
6
9
  function getEventType(eventClasses) {
7
10
  const typeClass = [...eventClasses]
8
11
  .find(className => className.startsWith("evt-"))
@@ -27,27 +30,25 @@ function getUrlDossierSenat(lienElements) {
27
30
  return urlElement ? urlElement.getAttribute("href") : null;
28
31
  }
29
32
  function getQuantieme(eventElement, seancesElements) {
30
- if (eventElement.classList.contains("evt-seance")) {
31
- const seanceIndex = seancesElements.indexOf(eventElement);
32
- if (seancesElements.length === 1 && seanceIndex === 0) {
33
- return "Unique";
34
- }
35
- else {
36
- switch (seanceIndex) {
37
- case 0:
38
- return "Première";
39
- case 1:
40
- return "Deuxième";
41
- case 2:
42
- return "Troisième";
43
- case 3:
44
- return "Quatrième";
45
- case 4:
46
- return "Cinquième";
47
- }
33
+ const seanceIndex = seancesElements.indexOf(eventElement);
34
+ if (seancesElements.length === 1 && seanceIndex === 0) {
35
+ return "Unique";
36
+ }
37
+ else {
38
+ switch (seanceIndex) {
39
+ case 0:
40
+ return "Première";
41
+ case 1:
42
+ return "Deuxième";
43
+ case 2:
44
+ return "Troisième";
45
+ case 3:
46
+ return "Quatrième";
47
+ case 4:
48
+ return "Cinquième";
48
49
  }
49
50
  }
50
- return null;
51
+ return "Non défini";
51
52
  }
52
53
  /**
53
54
  * Normalize time string to become a simple start time ("H'h'mm") or a duration ("'de 'H'h'mm' à 'H'h'mm").
@@ -85,8 +86,7 @@ function getStartAndEndTimes(timeStr) {
85
86
  function transformAgenda(document, fileName) {
86
87
  const agendaEvents = [];
87
88
  const eventElements = document.querySelectorAll(".evt");
88
- const seanceElements = Array.from(eventElements)
89
- .filter(eventElement => eventElement.classList.contains("evt-seance"));
89
+ const seanceElements = Array.from(eventElements).filter(eventElement => eventIsSeance(eventElement));
90
90
  for (const eventElement of eventElements) {
91
91
  const id = eventElement.previousElementSibling?.getAttribute("name") || null;
92
92
  if (!id) {
@@ -118,7 +118,7 @@ function transformAgenda(document, fileName) {
118
118
  lieu,
119
119
  captationVideo: videoElement !== null,
120
120
  urlDossierSenat: urlDossierSenat,
121
- quantieme: getQuantieme(eventElement, seanceElements),
121
+ quantieme: eventIsSeance(eventElement) ? getQuantieme(eventElement, seanceElements) : null,
122
122
  });
123
123
  }
124
124
  return agendaEvents;
@@ -0,0 +1,57 @@
1
+ import { sesFieldsToParseInt, sesFieldsToTrim, subFieldsToParseInt, subFieldsToTrim, txtAmeliFieldsToTrim, } from "../types/ameli";
2
+ import { dbByName } from "../databases";
3
+ import { parseIntFields, trimFieldsRight } from "../fields";
4
+ export const getSessFromAnns = async (ids) => {
5
+ if (ids.length === 0) {
6
+ return [];
7
+ }
8
+ return (await dbByName.ameli.any(`
9
+ SELECT *
10
+ FROM ses
11
+ WHERE ann IN ($<ids:list>)
12
+ `, {
13
+ ids,
14
+ })).map((ses) => parseIntFields(sesFieldsToParseInt, trimFieldsRight(sesFieldsToTrim, ses)));
15
+ };
16
+ export const getSubsFromTxtids = async (ids) => {
17
+ if (ids.length === 0) {
18
+ return [];
19
+ }
20
+ return (await dbByName.ameli.any(`
21
+ SELECT *
22
+ FROM sub
23
+ WHERE txtid IN($<ids:list>)
24
+ `, {
25
+ ids,
26
+ })).map((sub) => parseIntFields(subFieldsToParseInt, trimFieldsRight(subFieldsToTrim, sub)));
27
+ };
28
+ export const getTxtsAmeliBySesannNumJoins = async (ids) => {
29
+ if (ids.length === 0) {
30
+ return [];
31
+ }
32
+ const txtsAmelis = [];
33
+ for (const id of ids) {
34
+ const idSplit = id.split(" ");
35
+ const sesann = parseInt(idSplit[0]);
36
+ const num = idSplit[1];
37
+ const txtAmeli = trimFieldsRight(txtAmeliFieldsToTrim, await dbByName.ameli.oneOrNone(`
38
+ SELECT *
39
+ FROM txt_ameli
40
+ WHERE
41
+ sesinsid in (
42
+ SELECT id
43
+ FROM ses
44
+ WHERE ann = $<sesann>
45
+ ) AND
46
+ num = $<num>
47
+ LIMIT 1
48
+ `, {
49
+ num,
50
+ sesann,
51
+ }));
52
+ if (txtAmeli !== null) {
53
+ txtsAmelis.push(txtAmeli);
54
+ }
55
+ }
56
+ return txtsAmelis;
57
+ };
@@ -0,0 +1,86 @@
1
+ import {
2
+ Ses, sesFieldsToParseInt, sesFieldsToTrim,
3
+ Sub, subFieldsToParseInt, subFieldsToTrim,
4
+ TxtAmeli, txtAmeliFieldsToTrim,
5
+ } from "../types/ameli"
6
+ import { dbByName } from "../databases"
7
+ import { parseIntFields, trimFieldsRight } from "../fields"
8
+
9
+ export const getSessFromAnns = async (ids: string[]): Promise<Ses[]> => {
10
+ if (ids.length === 0) {
11
+ return []
12
+ }
13
+ return (
14
+ await dbByName.ameli.any(
15
+ `
16
+ SELECT *
17
+ FROM ses
18
+ WHERE ann IN ($<ids:list>)
19
+ `,
20
+ {
21
+ ids,
22
+ },
23
+ )
24
+ ).map((ses: Ses) =>
25
+ parseIntFields(sesFieldsToParseInt, trimFieldsRight(sesFieldsToTrim, ses)),
26
+ )
27
+ }
28
+
29
+ export const getSubsFromTxtids = async (ids: string[]): Promise<Sub[]> => {
30
+ if (ids.length === 0) {
31
+ return []
32
+ }
33
+ return (
34
+ await dbByName.ameli.any(
35
+ `
36
+ SELECT *
37
+ FROM sub
38
+ WHERE txtid IN($<ids:list>)
39
+ `,
40
+ {
41
+ ids,
42
+ },
43
+ )
44
+ ).map((sub: Sub) =>
45
+ parseIntFields(subFieldsToParseInt, trimFieldsRight(subFieldsToTrim, sub)),
46
+ )
47
+ }
48
+
49
+ export const getTxtsAmeliBySesannNumJoins = async (
50
+ ids: string[],
51
+ ): Promise<TxtAmeli[]> => {
52
+ if (ids.length === 0) {
53
+ return []
54
+ }
55
+ const txtsAmelis = []
56
+ for (const id of ids) {
57
+ const idSplit = id.split(" ")
58
+ const sesann = parseInt(idSplit[0])
59
+ const num = idSplit[1]
60
+ const txtAmeli = trimFieldsRight(
61
+ txtAmeliFieldsToTrim,
62
+ await dbByName.ameli.oneOrNone(
63
+ `
64
+ SELECT *
65
+ FROM txt_ameli
66
+ WHERE
67
+ sesinsid in (
68
+ SELECT id
69
+ FROM ses
70
+ WHERE ann = $<sesann>
71
+ ) AND
72
+ num = $<num>
73
+ LIMIT 1
74
+ `,
75
+ {
76
+ num,
77
+ sesann,
78
+ },
79
+ ),
80
+ ) as TxtAmeli
81
+ if (txtAmeli !== null) {
82
+ txtsAmelis.push(txtAmeli)
83
+ }
84
+ }
85
+ return txtsAmelis
86
+ }
@@ -0,0 +1,43 @@
1
+ import { debatsFieldsToTrim, lecassdebFieldsToTrim, } from "../types/debats";
2
+ import { dbByName } from "../databases";
3
+ import { trimFieldsRight } from "../fields";
4
+ export const getDebats = async (ids) => {
5
+ if (ids.length === 0) {
6
+ return [];
7
+ }
8
+ return (await dbByName.debats.any(`
9
+ SELECT *
10
+ FROM debats
11
+ WHERE datsea IN ($<ids:list>)
12
+ `, {
13
+ ids,
14
+ })).map((debat) => trimFieldsRight(debatsFieldsToTrim, debat));
15
+ };
16
+ export const getDebatsFromLecassidts = async (ids) => {
17
+ if (ids.length === 0) {
18
+ return [];
19
+ }
20
+ return (await dbByName.debats.any(`
21
+ SELECT *
22
+ FROM debats
23
+ WHERE datsea IN (
24
+ SELECT datsea
25
+ FROM lecassdeb
26
+ WHERE lecassidt IN ($<ids:list>)
27
+ )
28
+ `, {
29
+ ids,
30
+ })).map((debat) => trimFieldsRight(debatsFieldsToTrim, debat));
31
+ };
32
+ export const getLecAssDebsFromDatseas = async (ids) => {
33
+ if (ids.length === 0) {
34
+ return [];
35
+ }
36
+ return (await dbByName.debats.any(`
37
+ SELECT *
38
+ FROM lecassdeb
39
+ WHERE datsea IN ($<ids:list>)
40
+ `, {
41
+ ids,
42
+ })).map((lecassdeb) => trimFieldsRight(lecassdebFieldsToTrim, lecassdeb));
43
+ };
@@ -0,0 +1,68 @@
1
+ import {
2
+ Debat, debatsFieldsToTrim,
3
+ LecAssDeb, lecassdebFieldsToTrim,
4
+ } from "../types/debats"
5
+ import { dbByName } from "../databases"
6
+ import { trimFieldsRight } from "../fields"
7
+
8
+ export const getDebats = async (ids: string[]): Promise<Debat[]> => {
9
+ if (ids.length === 0) {
10
+ return []
11
+ }
12
+ return (
13
+ await dbByName.debats.any(
14
+ `
15
+ SELECT *
16
+ FROM debats
17
+ WHERE datsea IN ($<ids:list>)
18
+ `,
19
+ {
20
+ ids,
21
+ },
22
+ )
23
+ ).map((debat: Debat) => trimFieldsRight(debatsFieldsToTrim, debat))
24
+ }
25
+
26
+ export const getDebatsFromLecassidts = async (
27
+ ids: string[],
28
+ ): Promise<Debat[]> => {
29
+ if (ids.length === 0) {
30
+ return []
31
+ }
32
+ return (
33
+ await dbByName.debats.any(
34
+ `
35
+ SELECT *
36
+ FROM debats
37
+ WHERE datsea IN (
38
+ SELECT datsea
39
+ FROM lecassdeb
40
+ WHERE lecassidt IN ($<ids:list>)
41
+ )
42
+ `,
43
+ {
44
+ ids,
45
+ },
46
+ )
47
+ ).map((debat: Debat) => trimFieldsRight(debatsFieldsToTrim, debat))
48
+ }
49
+
50
+ export const getLecAssDebsFromDatseas = async (
51
+ ids: string[],
52
+ ): Promise<LecAssDeb[]> => {
53
+ if (ids.length === 0) {
54
+ return []
55
+ }
56
+ return (
57
+ await dbByName.debats.any(
58
+ `
59
+ SELECT *
60
+ FROM lecassdeb
61
+ WHERE datsea IN ($<ids:list>)
62
+ `,
63
+ {
64
+ ids,
65
+ },
66
+ )
67
+ ).map((lecassdeb: LecAssDeb) => trimFieldsRight(lecassdebFieldsToTrim, lecassdeb))
68
+ }
@@ -0,0 +1,163 @@
1
+ import { sql } from "kysely";
2
+ import { dbDosleg } from "../databases";
3
+ import { jsonArrayFrom } from "kysely/helpers/postgres";
4
+ function datesSeances(lectureAssembleeId) {
5
+ return jsonArrayFrom(dbDosleg.selectFrom("date_seance")
6
+ .where("date_seance.lecidt", "=", lectureAssembleeId)
7
+ .select([
8
+ "date_seance.date_s as date",
9
+ ]));
10
+ }
11
+ function organismesRapport(rapportId) {
12
+ return jsonArrayFrom(dbDosleg.selectFrom("org")
13
+ .leftJoin("raporg", "raporg.orgcod", "org.orgcod")
14
+ .where("raporg.rapcod", "=", rapportId)
15
+ .select([
16
+ "org.orgnom as libelle",
17
+ ]));
18
+ }
19
+ function auteursRapport(rapportId) {
20
+ return jsonArrayFrom(dbDosleg.selectFrom("auteur")
21
+ .leftJoin("ecr", "ecr.autcod", "auteur.autcod")
22
+ .where("ecr.rapcod", "=", rapportId)
23
+ .select([
24
+ "auteur.prenom as prenom",
25
+ "auteur.nomuse as nom_usuel",
26
+ "auteur.autmat as matricule",
27
+ ])
28
+ .orderBy("ecr.ecrnumtri", "asc"));
29
+ }
30
+ function rapports(lectureAssembleeId) {
31
+ return jsonArrayFrom(dbDosleg.selectFrom("rap")
32
+ .leftJoin("lecassrap", "lecassrap.rapcod", "rap.rapcod")
33
+ .leftJoin("denrap", "denrap.coddenrap", "rap.coddenrap")
34
+ .where("lecassrap.lecassidt", "=", lectureAssembleeId)
35
+ .select((eb) => [
36
+ "rap.rapnum as numero",
37
+ sql `rtrim(denrap.libdenrap)`.as("type_rapport"),
38
+ eb.case()
39
+ .when("rap.typurl", "=", "I")
40
+ .then(sql `concat('https://www.senat.fr/rap/', rtrim(rap.rapurl))`)
41
+ .else(sql `rtrim(rap.rapurl)`)
42
+ .end()
43
+ .as("url"),
44
+ "rap.date_depot as date_depot",
45
+ auteursRapport(eb.ref("rap.rapcod")).as("auteurs"),
46
+ organismesRapport(eb.ref("rap.rapcod")).as("organismes"),
47
+ ]));
48
+ }
49
+ function auteursTextes(texteId) {
50
+ return jsonArrayFrom(dbDosleg.selectFrom("auteur")
51
+ .leftJoin("ecr", "ecr.autcod", "auteur.autcod")
52
+ .where("ecr.texcod", "=", texteId)
53
+ .select([
54
+ "auteur.prenom as prenom",
55
+ "auteur.nomuse as nom_usuel",
56
+ "auteur.autmat as matricule",
57
+ ])
58
+ .orderBy("ecr.ecrnumtri", "asc"));
59
+ }
60
+ function textes(lectureAssembleeId) {
61
+ return jsonArrayFrom(dbDosleg.selectFrom("texte")
62
+ .leftJoin("oritxt", "oritxt.oritxtcod", "texte.oritxtcod")
63
+ .leftJoin("typtxt", "typtxt.typtxtcod", "texte.typtxtcod")
64
+ .where("texte.lecassidt", "=", lectureAssembleeId)
65
+ .select((eb) => [
66
+ "texte.texnum as numero",
67
+ eb.case()
68
+ .when("texte.typurl", "=", "I")
69
+ .then(sql `concat('https://www.senat.fr/leg/', rtrim(texte.texurl))`)
70
+ .else(sql `rtrim(texte.texurl)`)
71
+ .end()
72
+ .as("url"),
73
+ sql `rtrim(oritxt.oritxtlib)`.as("origine_texte"),
74
+ sql `rtrim(typtxt.typtxtlib)`.as("type_texte"),
75
+ "texte.txtoritxtdat as date",
76
+ "sesann as session",
77
+ auteursTextes(eb.ref("texte.texcod")).as("auteurs"),
78
+ ])
79
+ .orderBy(sql `array_position(array['0','2','1'], oritxt.oriordre)`));
80
+ }
81
+ function lecturesAssemblee(lectureId) {
82
+ return jsonArrayFrom(dbDosleg.selectFrom("lecass")
83
+ .where("lecass.lecidt", "=", lectureId)
84
+ .leftJoin("ass", "ass.codass", "lecass.codass")
85
+ .leftJoin("org", "org.orgcod", "lecass.orgcod")
86
+ .select(({ ref }) => [
87
+ sql `rtrim(ass.libass)`.as("assemblee"),
88
+ "org.orgnom as libelle_organisme",
89
+ textes(ref("lecass.lecassidt")).as("textes"),
90
+ rapports(ref("lecass.lecassidt")).as("rapports"),
91
+ datesSeances(ref("lecass.lecassidt")).as("dates_seances"),
92
+ ])
93
+ .orderBy("lecass.ordreass", "asc"));
94
+ }
95
+ function lectures(loiId) {
96
+ return jsonArrayFrom(dbDosleg.selectFrom("lecture")
97
+ .leftJoin("typlec", "typlec.typleccod", "lecture.typleccod")
98
+ .where("lecture.loicod", "=", loiId)
99
+ .select(({ ref }) => [
100
+ sql `rtrim(typlec.typleclib)`.as("type_lecture"),
101
+ sql `rtrim(lecture.leccom)`.as("libelle"),
102
+ lecturesAssemblee(ref("lecture.lecidt")).as("lectures_assemblee"),
103
+ ])
104
+ .orderBy("typlec.typlecord", "asc"));
105
+ }
106
+ function themes(loiId) {
107
+ return jsonArrayFrom(dbDosleg.selectFrom("the")
108
+ .leftJoin("loithe", "loithe.thecle", "the.thecle")
109
+ .where("loithe.loicod", "=", loiId)
110
+ .select([
111
+ "the.thelib as libelle",
112
+ ]));
113
+ }
114
+ const findAllQuery = dbDosleg
115
+ .selectFrom("loi")
116
+ .leftJoin("typloi", "typloi.typloicod", "loi.typloicod")
117
+ .leftJoin("etaloi", "etaloi.etaloicod", "loi.etaloicod")
118
+ .select(({ ref }) => [
119
+ "loi.signet as signet",
120
+ sql `concat('https://www.senat.fr/dossier-legislatif/', loi.signet, '.html')`.as("url"),
121
+ sql `concat(rtrim(typloi.typloilib), ' ', rtrim(loi.loitit))`.as("titre"),
122
+ sql `rtrim(typloi.typloilib)`.as("type_dossier"),
123
+ sql `rtrim(etaloi.etaloilib)`.as("etat_dossier"),
124
+ "loi.url_an as url_dossier_assemblee_nationale",
125
+ //" as decision_conseil_constitutionnel", // TODO
126
+ //" as date_decision_conseil_constitutionnel", // TODO
127
+ "loi.date_loi as date_promulgation",
128
+ "loi.numero as numero_loi",
129
+ lectures(ref("loi.loicod")).as("lectures"),
130
+ themes(ref("loi.loicod")).as("themes"),
131
+ ])
132
+ .$narrowType();
133
+ export function findAll() {
134
+ return findAllQuery.stream();
135
+ }
136
+ export function findSenatTexteUrls(sessions = []) {
137
+ return dbDosleg
138
+ .selectFrom("texte")
139
+ .where("texurl", "is not", null)
140
+ .where("typurl", "=", "I")
141
+ .$if(sessions.length > 0, (qb) => qb
142
+ .where("sesann", "in", sessions))
143
+ .select([
144
+ sql `rtrim(texurl)`.as("url"),
145
+ "sesann as session",
146
+ ])
147
+ .$narrowType()
148
+ .stream();
149
+ }
150
+ export function findSenatRapportUrls(sessions = []) {
151
+ return dbDosleg
152
+ .selectFrom("rap")
153
+ .where("rapurl", "is not", null)
154
+ .where("typurl", "=", "I")
155
+ .$if(sessions.length > 0, (qb) => qb
156
+ .where("sesann", "in", sessions))
157
+ .select([
158
+ sql `rtrim(rapurl)`.as("url"),
159
+ "sesann as session",
160
+ ])
161
+ .$narrowType()
162
+ .stream();
163
+ }