decidim-stratified_sortitions 0.0.1
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.
- checksums.yaml +7 -0
- data/LICENSE-AGPLv3.txt +661 -0
- data/README.md +91 -0
- data/Rakefile +42 -0
- data/app/cells/decidim/stratified_sortitions/stratified_sortition_cell.rb +21 -0
- data/app/cells/decidim/stratified_sortitions/stratified_sortition_l_cell.rb +22 -0
- data/app/cells/decidim/stratified_sortitions/stratified_sortition_metadata_cell.rb +63 -0
- data/app/commands/decidim/stratified_sortitions/admin/create_stratified_sortition.rb +84 -0
- data/app/commands/decidim/stratified_sortitions/admin/destroy_stratified_sortition.rb +49 -0
- data/app/commands/decidim/stratified_sortitions/admin/duplicate_stratified_sortition.rb +74 -0
- data/app/commands/decidim/stratified_sortitions/admin/import_sample.rb +40 -0
- data/app/commands/decidim/stratified_sortitions/admin/remove_uploaded_samples.rb +53 -0
- data/app/commands/decidim/stratified_sortitions/admin/update_stratified_sortition.rb +174 -0
- data/app/controllers/concerns/decidim/stratified_sortitions/orderable_stratified_sortitions.rb +37 -0
- data/app/controllers/concerns/decidim/stratified_sortitions/strata_charts_data.rb +91 -0
- data/app/controllers/decidim/stratified_sortitions/admin/application_controller.rb +19 -0
- data/app/controllers/decidim/stratified_sortitions/admin/samples_controller.rb +143 -0
- data/app/controllers/decidim/stratified_sortitions/admin/stratified_sortitions_controller.rb +235 -0
- data/app/controllers/decidim/stratified_sortitions/application_controller.rb +13 -0
- data/app/controllers/decidim/stratified_sortitions/charts_pdf_controller_helper.rb +17 -0
- data/app/controllers/decidim/stratified_sortitions/stratified_sortitions_controller.rb +61 -0
- data/app/forms/decidim/stratified_sortitions/admin/sample_upload_form.rb +15 -0
- data/app/forms/decidim/stratified_sortitions/admin/stratified_sortitions_form.rb +155 -0
- data/app/forms/decidim/stratified_sortitions/admin/stratum_form.rb +69 -0
- data/app/forms/decidim/stratified_sortitions/admin/substratum_form.rb +26 -0
- data/app/helpers/decidim/stratified_sortitions/admin/stratified_sortitions_helper.rb +18 -0
- data/app/helpers/decidim/stratified_sortitions/application_helper.rb +85 -0
- data/app/helpers/decidim/stratified_sortitions/charts_pdf_helper.rb +73 -0
- data/app/helpers/decidim/stratified_sortitions/stratified_sortition_cells_helper.rb +56 -0
- data/app/javascript/channels/sample_import_progress.js +12 -0
- data/app/jobs/decidim/stratified_sortitions/admin/execute_sortition_job.rb +21 -0
- data/app/jobs/decidim/stratified_sortitions/admin/import_sample_job.rb +170 -0
- data/app/jobs/decidim/stratified_sortitions/admin/remove_samples_job.rb +19 -0
- data/app/jobs/decidim/stratified_sortitions/admin/sortition_results_export_job.rb +28 -0
- data/app/mailers/decidim/stratified_sortitions/admin/import_mailer.rb +26 -0
- data/app/models/decidim/stratified_sortitions/application_record.rb +9 -0
- data/app/models/decidim/stratified_sortitions/panel_portfolio.rb +165 -0
- data/app/models/decidim/stratified_sortitions/sample_import.rb +14 -0
- data/app/models/decidim/stratified_sortitions/sample_participant.rb +12 -0
- data/app/models/decidim/stratified_sortitions/sample_participant_stratum.rb +11 -0
- data/app/models/decidim/stratified_sortitions/stratified_sortition.rb +74 -0
- data/app/models/decidim/stratified_sortitions/stratum.rb +22 -0
- data/app/models/decidim/stratified_sortitions/substratum.rb +19 -0
- data/app/packs/entrypoints/decidim_stratified_sortitions.js +10 -0
- data/app/packs/entrypoints/decidim_stratified_sortitions_admin.js +9 -0
- data/app/packs/entrypoints/decidim_stratified_sortitions_admin.scss +1 -0
- data/app/packs/images/decidim/stratified_sortitions/icon.svg +1 -0
- data/app/packs/src/decidim/stratified_sortitions/application.js +3 -0
- data/app/packs/src/decidim/stratified_sortitions/results_tabs.js +59 -0
- data/app/packs/src/decidim/stratified_sortitions/stratum_fields.js +302 -0
- data/app/packs/src/decidim/stratified_sortitions/substratum_fields.js +165 -0
- data/app/packs/src/decidim/stratified_sortitions/upload_sample.js +16 -0
- data/app/packs/stylesheets/decidim/stratified_sortitions/admin/stratified_sortitions.scss +210 -0
- data/app/packs/stylesheets/decidim/stratified_sortitions/charts_pdf.scss +148 -0
- data/app/packs/stylesheets/stratified_sortitions.scss +56 -0
- data/app/permissions/decidim/stratified_sortitions/admin/permissions.rb +74 -0
- data/app/permissions/decidim/stratified_sortitions/permissions.rb +23 -0
- data/app/presenters/decidim/stratified_sortitions/admin_log/stratified_sortition_presenter.rb +35 -0
- data/app/queries/decidim/stratified_sortitions/filtered_stratified_sortitions.rb +39 -0
- data/app/serializers/decidim/stratified_sortitions/sortition_result_serializer.rb +116 -0
- data/app/services/decidim/stratified_sortitions/charts_pdf_generator.rb +96 -0
- data/app/services/decidim/stratified_sortitions/fair_sortition_service.rb +247 -0
- data/app/services/decidim/stratified_sortitions/leximin/constraint_builder.rb +180 -0
- data/app/services/decidim/stratified_sortitions/leximin/distribution_solver.rb +217 -0
- data/app/services/decidim/stratified_sortitions/leximin/feasibility_checker.rb +222 -0
- data/app/services/decidim/stratified_sortitions/leximin/panel_generator.rb +149 -0
- data/app/services/decidim/stratified_sortitions/leximin/panel_sampler.rb +125 -0
- data/app/services/decidim/stratified_sortitions/leximin_selector.rb +136 -0
- data/app/services/decidim/stratified_sortitions/sortition_results_exporter.rb +161 -0
- data/app/views/decidim/admin/components/index.html.erb +54 -0
- data/app/views/decidim/stratified_sortitions/admin/import_mailer/import.html.erb +22 -0
- data/app/views/decidim/stratified_sortitions/admin/stratified_sortitions/_confirm_execute_modal.html.erb +19 -0
- data/app/views/decidim/stratified_sortitions/admin/stratified_sortitions/_confirm_participants_modal.html.erb +20 -0
- data/app/views/decidim/stratified_sortitions/admin/stratified_sortitions/_form.html.erb +55 -0
- data/app/views/decidim/stratified_sortitions/admin/stratified_sortitions/_navigation_menu.html.erb +10 -0
- data/app/views/decidim/stratified_sortitions/admin/stratified_sortitions/_strata.html.erb +22 -0
- data/app/views/decidim/stratified_sortitions/admin/stratified_sortitions/_stratum.html.erb +75 -0
- data/app/views/decidim/stratified_sortitions/admin/stratified_sortitions/_substrata.html.erb +34 -0
- data/app/views/decidim/stratified_sortitions/admin/stratified_sortitions/_substratum.html.erb +54 -0
- data/app/views/decidim/stratified_sortitions/admin/stratified_sortitions/edit.html.erb +21 -0
- data/app/views/decidim/stratified_sortitions/admin/stratified_sortitions/execute.html.erb +155 -0
- data/app/views/decidim/stratified_sortitions/admin/stratified_sortitions/export_charts_pdf.html.erb +38 -0
- data/app/views/decidim/stratified_sortitions/admin/stratified_sortitions/index.html.erb +75 -0
- data/app/views/decidim/stratified_sortitions/admin/stratified_sortitions/new.html.erb +21 -0
- data/app/views/decidim/stratified_sortitions/admin/stratified_sortitions/upload_sample.html.erb +117 -0
- data/app/views/decidim/stratified_sortitions/shared/_strata_charts.html.erb +21 -0
- data/app/views/decidim/stratified_sortitions/stratified_sortitions/_results_count.html.erb +15 -0
- data/app/views/decidim/stratified_sortitions/stratified_sortitions/_stratified_sortition.html.erb +1 -0
- data/app/views/decidim/stratified_sortitions/stratified_sortitions/_stratified_sortitions.html.erb +13 -0
- data/app/views/decidim/stratified_sortitions/stratified_sortitions/_tags.html.erb +9 -0
- data/app/views/decidim/stratified_sortitions/stratified_sortitions/index.html.erb +22 -0
- data/app/views/decidim/stratified_sortitions/stratified_sortitions/index.js.erb +5 -0
- data/app/views/decidim/stratified_sortitions/stratified_sortitions/show.html.erb +142 -0
- data/app/views/layouts/decidim/admin/_sidebar_menu.html.erb +45 -0
- data/app/views/layouts/decidim/stratified_sortitions/charts_pdf.html.erb +14 -0
- data/config/assets.rb +24 -0
- data/config/locales/ca.yml +361 -0
- data/config/locales/en.yml +360 -0
- data/config/locales/es.yml +360 -0
- data/config/locales/oc.yml +2 -0
- data/config/routes.rb +1 -0
- data/db/migrate/20251023103900_create_decidim_stratified_sortitions_stratified_sortitions.rb +18 -0
- data/db/migrate/20251104120000_create_stratified_sortitions_strata_and_substrata.decidim_stratified_sortitions.rb +27 -0
- data/db/migrate/20251219120000_create_sample_imports.rb +17 -0
- data/db/migrate/20251219120100_create_sample_participants.rb +19 -0
- data/db/migrate/20251219120200_create_sample_participant_strata.rb +16 -0
- data/db/migrate/20251230130000_change_value_to_text_in_substrata.rb +11 -0
- data/db/migrate/20260102114744_add_status_to_stratified_sortitions.rb +11 -0
- data/db/migrate/20260109105643_allow_null_value_in_substrata.rb +10 -0
- data/db/migrate/20260113121726_add_position_to_strata_and_substrata.rb +8 -0
- data/db/migrate/20260127100000_rename_weighing_to_max_quota_percentage.rb +12 -0
- data/db/migrate/20260127120000_create_panel_portfolios.rb +46 -0
- data/db/migrate/20260518000000_add_foreign_key_to_stratified_sortitions_component.rb +10 -0
- data/db/migrate/20260521000000_add_cascade_to_stratified_sortitions_foreign_keys.rb +64 -0
- data/db/migrate/20260616000000_add_execution_error_to_stratified_sortitions.rb +11 -0
- data/lib/decidim/stratified_sortitions/admin.rb +10 -0
- data/lib/decidim/stratified_sortitions/admin_engine.rb +49 -0
- data/lib/decidim/stratified_sortitions/component.rb +41 -0
- data/lib/decidim/stratified_sortitions/engine.rb +34 -0
- data/lib/decidim/stratified_sortitions/seeds.rb +24 -0
- data/lib/decidim/stratified_sortitions/test/factories.rb +80 -0
- data/lib/decidim/stratified_sortitions/version.rb +13 -0
- data/lib/decidim/stratified_sortitions.rb +29 -0
- metadata +222 -0
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
---
|
|
2
|
+
es:
|
|
3
|
+
activemodel:
|
|
4
|
+
attributes:
|
|
5
|
+
stratified_sortition:
|
|
6
|
+
created_at: Fecha de creación
|
|
7
|
+
title: Título
|
|
8
|
+
description: Descripción
|
|
9
|
+
num_candidates: Número de personas candidatas a seleccionar
|
|
10
|
+
selection_criteria: Criterios de elegibilidad
|
|
11
|
+
selected_profiles_description: Descripción de los perfiles a seleccionar
|
|
12
|
+
errors:
|
|
13
|
+
messages:
|
|
14
|
+
cannot_add_strata_with_sample_participants: "No se pueden añadir estratos cuando ya hay participantes importados"
|
|
15
|
+
cannot_delete_strata_with_sample_participants: "No se pueden eliminar estratos cuando ya hay participantes importados"
|
|
16
|
+
cannot_change_stratum_name_with_sample_participants: "No se puede cambiar el nombre del estrato cuando ya hay participantes importados"
|
|
17
|
+
cannot_change_stratum_kind_with_sample_participants: "No se puede cambiar el tipo del estrato cuando ya hay participantes importados"
|
|
18
|
+
cannot_add_substrata_with_sample_participants: "No se pueden añadir subestratos cuando ya hay participantes importados"
|
|
19
|
+
cannot_delete_substrata_with_sample_participants: "No se pueden eliminar subestratos cuando ya hay participantes importados"
|
|
20
|
+
cannot_change_substratum_name_with_sample_participants: "No se puede cambiar el nombre del subestrato cuando ya hay participantes importados"
|
|
21
|
+
cannot_change_substratum_value_with_sample_participants: "No se puede cambiar el valor del subestrato cuando ya hay participantes importados"
|
|
22
|
+
cannot_change_substratum_range_with_sample_participants: "No se puede cambiar el rango del subestrato cuando ya hay participantes importados"
|
|
23
|
+
cannot_change_num_candidates_when_executed: "No se puede cambiar el número de candidatos después de que el sorteo haya sido ejecutado"
|
|
24
|
+
decidim:
|
|
25
|
+
admin:
|
|
26
|
+
components:
|
|
27
|
+
index:
|
|
28
|
+
headers:
|
|
29
|
+
scope: Ámbito
|
|
30
|
+
components:
|
|
31
|
+
stratified_sortitions:
|
|
32
|
+
name: Sorteos estratificados
|
|
33
|
+
settings:
|
|
34
|
+
global:
|
|
35
|
+
announcement: Aviso
|
|
36
|
+
publish_sortitions: Publicar gráficos comparativos de los sorteos
|
|
37
|
+
step:
|
|
38
|
+
announcement: Aviso
|
|
39
|
+
stratified_sortitions:
|
|
40
|
+
admin:
|
|
41
|
+
actions:
|
|
42
|
+
configure: Configurar
|
|
43
|
+
confirm_destroy: ¿Estás seguro de que quieres eliminar este %{name}?
|
|
44
|
+
destroy: Eliminar
|
|
45
|
+
duplicate: Duplicar
|
|
46
|
+
execute: Ejecutar sorteo
|
|
47
|
+
new_stratified_sortition: "Nuevo sorteo estratificado"
|
|
48
|
+
title: "Acciones"
|
|
49
|
+
census_management: Gestionar muestra
|
|
50
|
+
models:
|
|
51
|
+
stratified_sortition:
|
|
52
|
+
fields:
|
|
53
|
+
created_at: Fecha de creación
|
|
54
|
+
title: Título
|
|
55
|
+
description: Descripción
|
|
56
|
+
num_candidates: Número de candidatas a seleccionar
|
|
57
|
+
selection_criteria: Criterios de elegibilidad
|
|
58
|
+
selected_profiles_description: Descripción de los perfiles a seleccionar
|
|
59
|
+
status: Estado
|
|
60
|
+
stratified_sortitions:
|
|
61
|
+
create:
|
|
62
|
+
error: Ha habido un problema al crear este sorteo estratificado
|
|
63
|
+
success: Sorteo estratificado creado con éxito
|
|
64
|
+
destroy:
|
|
65
|
+
error: Ha habido un problema al eliminar este sorteo estratificado
|
|
66
|
+
has_problems: Este sorteo estratificado no se pudo eliminar debido a problemas relacionados
|
|
67
|
+
success: Sorteo estratificado eliminado con éxito
|
|
68
|
+
execute:
|
|
69
|
+
candidates: Candidatos
|
|
70
|
+
chart_results: Gráficos de distribución
|
|
71
|
+
tab_charts: Gráficos comparativos
|
|
72
|
+
tab_participants: Participantes seleccionados
|
|
73
|
+
empty_sample_participants: No se puede ejecutar el sorteo sin un censo cargado
|
|
74
|
+
execute_stratified_sortition: Ejecutar sorteo estratificado
|
|
75
|
+
confirm_execute_title: Confirmación
|
|
76
|
+
confirm_execute_body: Al ejecutar el sorteo este quedará registrado a la plataforma y la acción será irreversible. No se podrán editar los datos, la configuración de los estratos ni la muestra.
|
|
77
|
+
confirm_execute_ok: Ejecutar sorteo
|
|
78
|
+
confirm_execute_cancel: Cancelar
|
|
79
|
+
export: Exportar
|
|
80
|
+
export_results: Exportar resultados
|
|
81
|
+
export_csv: Resultados del sorteo estratificado como CSV
|
|
82
|
+
export_excel: Resultados del sorteo estratificado como Excel
|
|
83
|
+
export_json: Resultados del sorteo estratificado como JSON
|
|
84
|
+
export_charts_pdf: Exportar gráficos PDF
|
|
85
|
+
pdf_title: "Resultados del sorteo %{name}"
|
|
86
|
+
pdf_subtitle: Gráficos comparativos de distribución de la muestra
|
|
87
|
+
pdf_belongs_to: "Pertenece a: %{space_name}"
|
|
88
|
+
pdf_algorithm: "Algoritmo usado: %{algorithm}"
|
|
89
|
+
pdf_executed_at: "Sorteo realizado el: %{date}"
|
|
90
|
+
pdf_no_data: Sin datos
|
|
91
|
+
algorithm: Algoritmo
|
|
92
|
+
generated_at: Generado el
|
|
93
|
+
generation_time: Tiempo de generación
|
|
94
|
+
total_participants: Total de participantes
|
|
95
|
+
num_panels: Número de paneles
|
|
96
|
+
selected_at: Seleccionado el
|
|
97
|
+
verification_seed: Seed de verificación
|
|
98
|
+
random_value_used: Valor aleatorio utilizado
|
|
99
|
+
selected_panel_probability: Probabilidad del panel seleccionado
|
|
100
|
+
selected_participants_title: Participantes seleccionados
|
|
101
|
+
selected_participants:
|
|
102
|
+
one: "1 participante seleccionado"
|
|
103
|
+
other: "%{count} participantes seleccionados"
|
|
104
|
+
participant_id: ID
|
|
105
|
+
personal_data_1: Dato personal 1
|
|
106
|
+
personal_data_2: Dato personal 2
|
|
107
|
+
personal_data_3: Dato personal 3
|
|
108
|
+
personal_data_4: Dato personal 4
|
|
109
|
+
no_results_yet: El sorteo aún no se ha ejecutado.
|
|
110
|
+
confirm_participants_title: Muestra el listado de las participantes seleccionadas
|
|
111
|
+
confirm_participants_body: Estás accediendo a información y datos personales. Esta acción quedará registrada.
|
|
112
|
+
confirm_participants_ok: Muestra
|
|
113
|
+
confirm_participants_cancel: Cancelar
|
|
114
|
+
results: Resultados
|
|
115
|
+
executing_notice: El sorteo se está procesando en segundo plano. Esta página se actualizará cuando haya finalizado.
|
|
116
|
+
execution_failed: "La ejecución del sorteo ha fallado:"
|
|
117
|
+
success: Sorteo estratificado ejecutado con éxito
|
|
118
|
+
executing: El sorteo ha sido encolado y se está procesando en segundo plano.
|
|
119
|
+
target: Objetivo
|
|
120
|
+
title: Ejecutar sorteo estratificado
|
|
121
|
+
export_results:
|
|
122
|
+
no_results: No hay resultados para exportar. Ejecute el sorteo primero.
|
|
123
|
+
duplicate:
|
|
124
|
+
error: Ha habido un problema al duplicar este sorteo estratificado
|
|
125
|
+
success: Sorteo estratificado duplicado con éxito
|
|
126
|
+
index:
|
|
127
|
+
selected: Sorteos estratificados seleccionados
|
|
128
|
+
title: Sorteos estratificados
|
|
129
|
+
new:
|
|
130
|
+
create: Crear
|
|
131
|
+
title: Nuevo sorteo estratificado
|
|
132
|
+
edit:
|
|
133
|
+
title: Editar sorteo estratificado
|
|
134
|
+
update: Actualizar
|
|
135
|
+
form:
|
|
136
|
+
data: Información general
|
|
137
|
+
description: Descripción
|
|
138
|
+
name: Nombre
|
|
139
|
+
published: Publicado
|
|
140
|
+
selected_profiles_description_help: Puedes indicar, si corresponde, los criterios de estratificación utilizados en el sorteo, y la razón.
|
|
141
|
+
selection_criteria_help: Puedes indicar, si corresponde, los criterios de elegibilidad de las personas que han sido seleccionadas para participar en el sorteo.
|
|
142
|
+
strata:
|
|
143
|
+
title: Estratos
|
|
144
|
+
add_stratum: Añadir estrato
|
|
145
|
+
stratum:
|
|
146
|
+
up: Subir
|
|
147
|
+
down: Bajar
|
|
148
|
+
remove: Eliminar
|
|
149
|
+
name: Nombre
|
|
150
|
+
kind:
|
|
151
|
+
numeric_range: Rango numérico
|
|
152
|
+
title: Tipo
|
|
153
|
+
value: Valor
|
|
154
|
+
substrata_title: Subestratos
|
|
155
|
+
title: Estrato
|
|
156
|
+
substrata:
|
|
157
|
+
add_substratum: Añadir subestrato
|
|
158
|
+
substratum:
|
|
159
|
+
up: Subir
|
|
160
|
+
down: Bajar
|
|
161
|
+
remove: Eliminar
|
|
162
|
+
name: Nombre
|
|
163
|
+
value: Valor
|
|
164
|
+
value_placeholder: Valor
|
|
165
|
+
range: Rango
|
|
166
|
+
range_placeholder: Rango (p. ej. 0-18)
|
|
167
|
+
title: Subestrato
|
|
168
|
+
max_quota_percentage: Objetivo %
|
|
169
|
+
max_quota_percentage_placeholder: Objetivo %
|
|
170
|
+
update:
|
|
171
|
+
error: Ha habido un problema al actualizar este sorteo estratificado
|
|
172
|
+
success: Sorteo estratificado actualizado con éxito
|
|
173
|
+
upload_sample:
|
|
174
|
+
age: Grupo de edad
|
|
175
|
+
candidates: Candidatos
|
|
176
|
+
census_file: Elegir un archivo
|
|
177
|
+
census_file_label: Archivo excel.csv con los datos del censo
|
|
178
|
+
configure_strata_first: Primero debes configurar los estratos y subestratos
|
|
179
|
+
count_uploaded_files: "<b>%{count}</b> registros cargados."
|
|
180
|
+
description: El archivo de la muestra tiene que ser un CSV y tiene que tener un formatsimilar al del ejemplo siguiente:<br>Puedes descargar y utilizar la plantilla.
|
|
181
|
+
download_template: "Descargar plantilla"
|
|
182
|
+
download_template_csv: "Descargar plantilla como CSV"
|
|
183
|
+
download_template_xlsx: "Descargar plantilla como XLSX"
|
|
184
|
+
example: "Dato candidato 1,Dato candidato 2,Dato candidato 3,Dato candidato 4,Estrato 1,Estrato 2,Estrato 3,Estrato N<br>example@example.com,D,Superiores,34<br>example@example.com,E,Superiores,24<br><br>. . ."
|
|
185
|
+
example_headers:
|
|
186
|
+
personal_data_1: "Dato personal 1 (identificador único)"
|
|
187
|
+
personal_data_2: "Dato personal 2"
|
|
188
|
+
personal_data_3: "Dato personal 3"
|
|
189
|
+
personal_data_4: "Dato personal 4"
|
|
190
|
+
gender: "Género"
|
|
191
|
+
age: "Edad"
|
|
192
|
+
example_rows:
|
|
193
|
+
- - "11111111X"
|
|
194
|
+
- "Nombre ejemplo 1"
|
|
195
|
+
- "Teléfono Ejemplo 1"
|
|
196
|
+
- "correo1@ejemplo.com"
|
|
197
|
+
- "Hombre"
|
|
198
|
+
- "45"
|
|
199
|
+
- - "22222222Y"
|
|
200
|
+
- "Nombre ejemplo 2"
|
|
201
|
+
- "Teléfono Ejemplo 2"
|
|
202
|
+
- "correo2@ejemplo.com"
|
|
203
|
+
- "Mujer"
|
|
204
|
+
- "42"
|
|
205
|
+
execute_stratified_sortition: Ejecutar sorteo
|
|
206
|
+
execute_stratified_sortition_help: El sorteo no se puede ejecutar hasta que no se carguen registros.
|
|
207
|
+
filename_data: "%{filename}, el día %{date}, número de registros %{count}"
|
|
208
|
+
gender: Género
|
|
209
|
+
last_upload_date: La última carga fue el día %{date}
|
|
210
|
+
help: Las cuatro primeras columnas son datos del candidato, por ejemplo correo electrónico, DNI, teléfono o dirección y las siguientes columnas son los estratos definidos en el sorteo estratificado. Cada fila representa un candidato.
|
|
211
|
+
no_data: No hay datos
|
|
212
|
+
place: Lugar de nacimiento
|
|
213
|
+
remove_uploaded_samples: Eliminar todos los registros
|
|
214
|
+
confirm_remove_uploaded_samples: ¿Estás seguro de que quieres eliminar todas las muestras cargadas?
|
|
215
|
+
strata_not_configured: Primero debes configurar los estratos y subestratos
|
|
216
|
+
target: Objetivo
|
|
217
|
+
title: Gestionar muestra
|
|
218
|
+
upload_census: Subir una nueva muestra
|
|
219
|
+
upload_file: Subir nueva muestra
|
|
220
|
+
uploaded_file: Datos de la muestra cargada
|
|
221
|
+
uploaded_files: "Se han agregado los siguientes archivos:"
|
|
222
|
+
no_uploaded_files: "No hay archivos cargados."
|
|
223
|
+
help_csv: "<b>El archivo a cargar tiene que seguir las siguientes instrucciones:</b>
|
|
224
|
+
<ul><li>El formato del fichero tiene que ser .csv. Puedes descargar una plantilla.</li>
|
|
225
|
+
<li>La primera columna es obligatoria. Es el identificador único de cada participante y puede ser el DNI, un código generado aleatoriamente o cualquier otra forma de identificación que se quiera usar.</li>
|
|
226
|
+
<li>Las columnas 2,3 y 4 (Dato personal 2, 3, 4) son opcionales y no se utilizan para hacer el sorteo. Sirven para añadir los datos de contacto de cada participante.</li>
|
|
227
|
+
<li>Las columnas de los estratos son obligatorias y tienen que tener el mismo orden y nombre que el que hayamos configurado en el apartado anterior.</li>
|
|
228
|
+
<li>La información a incluir en las columnas tiene que coincidir con alguno de los Valores que hayamos indicado para cada estrato.</li>
|
|
229
|
+
<li>Si una participante no tiene datos en alguno de los estratos o no coincide con alguno de los valores configurados, será excluida del sorteo.</li></ul>"
|
|
230
|
+
help_submit: 'Al "Guardar" el sistema realizará la carga en segundo plano, puede tardar varios minutos dependiendo del volumen de participantes, por lo que al finalizar la carga será notificado vía email con el resultado.'
|
|
231
|
+
import_mailer:
|
|
232
|
+
subject: "Resultado de la importación de la muestra"
|
|
233
|
+
import:
|
|
234
|
+
ready: "La importación de la muestra ha finalizado correctamente."
|
|
235
|
+
total_rows: "Total de filas"
|
|
236
|
+
imported_rows: "Importadas correctamente"
|
|
237
|
+
failed_rows: "Filas con errores"
|
|
238
|
+
errors_summary: "Total de filas: %{total}. Importadas correctamente: %{imported}. Filas con errores: %{failed}."
|
|
239
|
+
see_details: "Los identificadores de los participantes los cuales han tenido error son:"
|
|
240
|
+
participant_id: "Identificador del participante:"
|
|
241
|
+
samples:
|
|
242
|
+
template:
|
|
243
|
+
personal_data_1: "Dato personal 1 (identificador único)"
|
|
244
|
+
personal_data_2: "Dato personal 2"
|
|
245
|
+
personal_data_3: "Dato personal 3"
|
|
246
|
+
personal_data_4: "Dato personal 4"
|
|
247
|
+
import_success: "La muestra se ha importado correctamente."
|
|
248
|
+
import_failed: "Ha ocurrido un error al importar la muestra: %{error}"
|
|
249
|
+
errors:
|
|
250
|
+
no_file: "No se ha seleccionado ningún archivo."
|
|
251
|
+
no_strata: "Debes configurar los estratos y subestratos antes de subir una muestra."
|
|
252
|
+
pending: "Solo puedes subir muestras cuando el sorteo estratificado está en estado pendiente."
|
|
253
|
+
sample_imports:
|
|
254
|
+
create:
|
|
255
|
+
success: "La muestra se está cargando en segundo plano. Cuando termine recibirás un correo con el resumen de la importación."
|
|
256
|
+
remove_uploaded_samples:
|
|
257
|
+
enqueued: "La eliminación de la muestra ha sido encolada y se procesará en segundo plano."
|
|
258
|
+
success: "Las muestras cargadas se han eliminado correctamente."
|
|
259
|
+
error: "Ha ocurrido un error al eliminar las muestras cargadas."
|
|
260
|
+
stratified_sortitions:
|
|
261
|
+
count:
|
|
262
|
+
candidates_count:
|
|
263
|
+
one: 1 candidato
|
|
264
|
+
other: "%{count} candidatos"
|
|
265
|
+
filters:
|
|
266
|
+
all: Todos
|
|
267
|
+
pending: Pendiente
|
|
268
|
+
executing: Ejecutando
|
|
269
|
+
executed: Ejecutado
|
|
270
|
+
failed: Fallido
|
|
271
|
+
state: Estado
|
|
272
|
+
index:
|
|
273
|
+
empty: Aún no hay sorteos estratificados.
|
|
274
|
+
orders:
|
|
275
|
+
label: 'Ordenar sorteos estratificados por:'
|
|
276
|
+
random: Aleatorio
|
|
277
|
+
recent: Reciente
|
|
278
|
+
results_count:
|
|
279
|
+
count:
|
|
280
|
+
one: Candidato a seleccionar
|
|
281
|
+
other: Candidatos a seleccionar
|
|
282
|
+
count_selected:
|
|
283
|
+
one: Candidato seleccionado
|
|
284
|
+
other: Candidatos seleccionados
|
|
285
|
+
show:
|
|
286
|
+
introduction: 'Esta página contiene los detalles del sorteo estratificado %{reference}. Mediante este sorteo, se han seleccionado %{num_candidates} candidatos utilizando un algoritmo de selección aleatoria estratificada que garantiza la representación justa en todos los estratos definidos.'
|
|
287
|
+
description: Descripción
|
|
288
|
+
selection_criteria: Criterios de elegibilidad
|
|
289
|
+
selected_profiles_description: Descripción de los perfiles seleccionados
|
|
290
|
+
to_be_selected_profiles_description: Descripción de los perfiles a seleccionar
|
|
291
|
+
strata: Estratos
|
|
292
|
+
max_quota: Cuota máxima
|
|
293
|
+
selected_participants: Participantes seleccionados
|
|
294
|
+
selected_participants_count:
|
|
295
|
+
one: Se ha seleccionado 1 participante
|
|
296
|
+
other: "Se han seleccionado %{count} participantes"
|
|
297
|
+
sortition_details: Detalles del sorteo
|
|
298
|
+
num_candidates: Número de candidatas a seleccionar
|
|
299
|
+
status: Estado
|
|
300
|
+
strata_count: Número de estratos
|
|
301
|
+
algorithm: Algoritmo
|
|
302
|
+
algorithm_name: LEXIMIN
|
|
303
|
+
algorithm_description: Algoritmo de selección aleatoria estratificada que garantiza la representación justa en todos los estratos definidos
|
|
304
|
+
reproducibility_details: Reproducibilidad del sorteo
|
|
305
|
+
verification_seed: Semilla de verificación
|
|
306
|
+
random_value_used: Valor aleatorio utilizado
|
|
307
|
+
selected_panel_index: Índice del panel seleccionado
|
|
308
|
+
selected_at: Seleccionado el
|
|
309
|
+
strata_charts: Distribución de los perfiles
|
|
310
|
+
target: Objetivo a conseguir
|
|
311
|
+
candidates: Candidaturas recibidas
|
|
312
|
+
no_data: Sin datos
|
|
313
|
+
results: Resultados del sorteo
|
|
314
|
+
statuses:
|
|
315
|
+
pending: Pendiente
|
|
316
|
+
executing: Ejecutando
|
|
317
|
+
executed: Ejecutado
|
|
318
|
+
failed: Fallido
|
|
319
|
+
stratified_sortition:
|
|
320
|
+
num_candidates: candidatos a seleccionar
|
|
321
|
+
strata_count: estratos
|
|
322
|
+
stratified_sortitions_count:
|
|
323
|
+
count:
|
|
324
|
+
one: 1 sorteo estratificado
|
|
325
|
+
other: "%{count} sorteos estratificados"
|
|
326
|
+
admin_log:
|
|
327
|
+
stratified_sortition:
|
|
328
|
+
create: "%{user_name} ha creado el sorteo estratificado %{resource_name} en %{space_name}"
|
|
329
|
+
update: "%{user_name} ha actualizado el sorteo estratificado %{resource_name} en %{space_name}"
|
|
330
|
+
delete: "%{user_name} ha eliminado el sorteo estratificado %{resource_name} en %{space_name}"
|
|
331
|
+
duplicate: "%{user_name} ha duplicado el sorteo estratificado %{resource_name}"
|
|
332
|
+
import_sample: "%{user_name} ha importado una muestra en el sorteo estratificado %{resource_name} en %{space_name}"
|
|
333
|
+
remove_samples: "%{user_name} ha eliminado los registros importados del sorteo estratificado %{resource_name} en %{space_name}"
|
|
334
|
+
execute: "%{user_name} ha ejecutado el sorteo estratificado %{resource_name} en %{space_name}"
|
|
335
|
+
export_results: "%{user_name} ha exportado los resultados del sorteo estratificado %{resource_name} en %{space_name}"
|
|
336
|
+
view_participants: "%{user_name} ha consultado el listado de participantes seleccionadas del sorteo estratificado %{resource_name} en %{space_name}"
|
|
337
|
+
errors:
|
|
338
|
+
panel_portfolio:
|
|
339
|
+
already_sampled: "La cartera ya ha sido muestreada"
|
|
340
|
+
probabilities_size_mismatch: "deben tener el mismo tamaño que los paneles (%{panels_count} paneles, %{probabilities_count} probabilidades)"
|
|
341
|
+
probabilities_sum_invalid: "deben sumar 1.0 (actualmente %{total})"
|
|
342
|
+
feasibility:
|
|
343
|
+
panel_size_positive: "El tamaño del panel (num_candidates) debe ser un número positivo"
|
|
344
|
+
no_categories: "No hay categorías (subestratos) definidas. Debe configurar los estratos y subestratos antes de ejecutar el algoritmo"
|
|
345
|
+
no_volunteers: "No hay voluntarios en el pool. Debe importar participantes antes de ejecutar el sorteo"
|
|
346
|
+
pool_too_small: "El pool de voluntarios (%{volunteers_count}) es más pequeño que el tamaño del panel (%{panel_size}). Agregue más participantes o reduzca el número de candidatos a seleccionar"
|
|
347
|
+
stratum_insufficient_quotas: "El estrato '%{stratum_name}' tiene cuotas máximas insuficientes. La suma de cuotas máximas (%{total_max}) es menor que el tamaño del panel (%{panel_size})"
|
|
348
|
+
stratum_percentages_exceed: "El estrato '%{stratum_name}' tiene porcentajes que suman más del 100%% (%{total_percentage}%%)"
|
|
349
|
+
substratum_insufficient_volunteers: "El subestrato '%{substratum_name}' del estrato '%{stratum_name}' requiere un mínimo de %{min_quota} voluntarios pero solo tiene %{volunteers_count}"
|
|
350
|
+
substratum_quota_exceeds_volunteers: "El subestrato '%{substratum_name}' del estrato '%{stratum_name}' tiene una cuota máxima de %{max_quota} (%{percentage}%%) pero solo %{volunteers_count} voluntario(s) pertenecen a esta categoría. Reduzca el porcentaje de cuota máxima o añada más participantes en esta categoría"
|
|
351
|
+
volunteers_missing_strata: "Hay %{count} voluntario(s) que no tienen asignado un subestrato para cada estrato. Esto puede causar problemas en el algoritmo de selección"
|
|
352
|
+
no_name: "Sin nombre"
|
|
353
|
+
fair_sortition:
|
|
354
|
+
already_performed: "El sorteo ya se ha realizado para este proceso"
|
|
355
|
+
portfolio_generation_failed: "Error generando la cartera de paneles: %{error}"
|
|
356
|
+
no_portfolio: "No hay cartera de paneles. Ejecute `generate_portfolio` primero"
|
|
357
|
+
sampling_failed: "Error en el muestreo: %{error}"
|
|
358
|
+
leximin:
|
|
359
|
+
no_feasible_panel: "No se pudo encontrar un panel inicial válido. La combinación de restricciones de cuota (porcentajes máximos) y la muestra disponible hacen imposible formar un panel. Posibles causas: (1) Los porcentajes de cuota máxima de algunos subestratos son demasiado restrictivos para el tamaño de la muestra disponible. (2) No hay suficientes participantes en ciertas combinaciones de subestratos. (3) El número de candidatos a seleccionar es demasiado grande en relación a la muestra. Intente ajustar los porcentajes de cuota máxima o cargue una muestra más grande."
|
|
360
|
+
internal_error: "Error interno en el algoritmo de selección: %{error}. Por favor, verifique que la configuración de los estratos y los porcentajes de cuota máxima son compatibles con la muestra cargada."
|
data/config/routes.rb
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class CreateDecidimStratifiedSortitionsStratifiedSortitions < ActiveRecord::Migration[5.2]
|
|
4
|
+
def change
|
|
5
|
+
create_table :decidim_stratified_sortitions_stratified_sortitions do |t|
|
|
6
|
+
t.jsonb :title
|
|
7
|
+
t.integer :num_candidates, null: false
|
|
8
|
+
t.jsonb :description
|
|
9
|
+
t.jsonb :selection_criteria
|
|
10
|
+
t.jsonb :selected_profiles_description
|
|
11
|
+
t.references :decidim_component, index: false, null: false
|
|
12
|
+
|
|
13
|
+
t.timestamps
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
add_index :decidim_stratified_sortitions_stratified_sortitions, :decidim_component_id, name: "index_decidim_stratified_sortitions_component_id"
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class CreateDecidimStratifiedSortitionsStrataAndSubstrata < ActiveRecord::Migration[7.0]
|
|
4
|
+
def change
|
|
5
|
+
create_table :decidim_stratified_sortitions_strata do |t|
|
|
6
|
+
t.jsonb :name, null: false, default: "{}"
|
|
7
|
+
t.string :kind, null: false
|
|
8
|
+
t.integer :decidim_stratified_sortition_id, null: false
|
|
9
|
+
|
|
10
|
+
t.timestamps
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
add_index :decidim_stratified_sortitions_strata, :decidim_stratified_sortition_id, name: "index_strata_on_sortition_id"
|
|
14
|
+
|
|
15
|
+
create_table :decidim_stratified_sortitions_substrata do |t|
|
|
16
|
+
t.jsonb :name, null: false, default: "{}"
|
|
17
|
+
t.jsonb :value, null: false, default: "{}"
|
|
18
|
+
t.string :range
|
|
19
|
+
t.string :weighing
|
|
20
|
+
t.integer :decidim_stratified_sortitions_stratum_id, null: false
|
|
21
|
+
|
|
22
|
+
t.timestamps
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
add_index :decidim_stratified_sortitions_substrata, :decidim_stratified_sortitions_stratum_id, name: "index_substrata_on_stratum_id"
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class CreateSampleImports < ActiveRecord::Migration[7.0]
|
|
4
|
+
def change
|
|
5
|
+
create_table :decidim_stratified_sortitions_sample_imports do |t|
|
|
6
|
+
t.references :stratified_sortition, null: false, foreign_key: { to_table: :decidim_stratified_sortitions_stratified_sortitions },
|
|
7
|
+
index: { name: "idx_sample_imports_on_sortition_id" }
|
|
8
|
+
t.string :filename
|
|
9
|
+
t.integer :total_rows, default: 0
|
|
10
|
+
t.integer :imported_rows, default: 0
|
|
11
|
+
t.integer :failed_rows, default: 0
|
|
12
|
+
t.jsonb :import_errors, default: {}
|
|
13
|
+
t.string :status, default: "pending"
|
|
14
|
+
t.timestamps
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class CreateSampleParticipants < ActiveRecord::Migration[7.0]
|
|
4
|
+
def change
|
|
5
|
+
create_table :decidim_stratified_sortitions_sample_participants do |t|
|
|
6
|
+
t.references :decidim_stratified_sortition, null: false, foreign_key: { to_table: :decidim_stratified_sortitions_stratified_sortitions },
|
|
7
|
+
index: { name: "idx_sample_part_on_sortition_id" }
|
|
8
|
+
t.references :decidim_stratified_sortitions_sample_import, foreign_key: { to_table: :decidim_stratified_sortitions_sample_imports },
|
|
9
|
+
index: { name: "idx_sample_part_on_sample_import_id" }
|
|
10
|
+
t.string :personal_data_1, null: false
|
|
11
|
+
t.string :personal_data_2
|
|
12
|
+
t.string :personal_data_3
|
|
13
|
+
t.string :personal_data_4
|
|
14
|
+
t.jsonb :column_values, default: []
|
|
15
|
+
t.string :reference_code
|
|
16
|
+
t.timestamps
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class CreateSampleParticipantStrata < ActiveRecord::Migration[7.0]
|
|
4
|
+
def change
|
|
5
|
+
create_table :decidim_stratified_sortitions_sample_participant_strata do |t|
|
|
6
|
+
t.references :decidim_stratified_sortitions_sample_participant, null: false, foreign_key: true, index: { name: "idx_sample_part_strata_on_participants" }
|
|
7
|
+
t.references :decidim_stratified_sortitions_stratum, null: false, foreign_key: true, index: { name: "idx_sample_part_strata_on_strata" }
|
|
8
|
+
t.references :decidim_stratified_sortitions_substratum,
|
|
9
|
+
null: true,
|
|
10
|
+
foreign_key: { to_table: :decidim_stratified_sortitions_substrata },
|
|
11
|
+
index: { name: "idx_sample_part_strata_on_substrata" }
|
|
12
|
+
t.string :raw_value
|
|
13
|
+
t.timestamps
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class ChangeValueToTextInSubstrata < ActiveRecord::Migration[7.0]
|
|
4
|
+
def up
|
|
5
|
+
change_column :decidim_stratified_sortitions_substrata, :value, :text
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def down
|
|
9
|
+
change_column :decidim_stratified_sortitions_substrata, :value, :jsonb
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class AddStatusToStratifiedSortitions < ActiveRecord::Migration[7.0]
|
|
4
|
+
def up
|
|
5
|
+
add_column :decidim_stratified_sortitions_stratified_sortitions, :status, :string, default: "pending"
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def down
|
|
9
|
+
remove_column :decidim_stratified_sortitions_stratified_sortitions, :status
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class AllowNullValueInSubstrata < ActiveRecord::Migration[7.0]
|
|
4
|
+
def change
|
|
5
|
+
change_table :decidim_stratified_sortitions_substrata, bulk: true do |t|
|
|
6
|
+
t.change_null :value, true
|
|
7
|
+
t.change_default :value, nil
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class AddPositionToStrataAndSubstrata < ActiveRecord::Migration[7.0]
|
|
4
|
+
def change
|
|
5
|
+
add_column :decidim_stratified_sortitions_substrata, :position, :integer
|
|
6
|
+
add_column :decidim_stratified_sortitions_strata, :position, :integer
|
|
7
|
+
end
|
|
8
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# This migration renames the 'weighing' column to 'max_quota_percentage' for clarity.
|
|
4
|
+
# The column stores the target percentage for each substratum category.
|
|
5
|
+
# For the LEXIMIN algorithm:
|
|
6
|
+
# - min_quota is implicitly 0 (no minimum required for any category)
|
|
7
|
+
# - max_quota is calculated as: (max_quota_percentage / 100.0) * panel_size
|
|
8
|
+
class RenameWeighingToMaxQuotaPercentage < ActiveRecord::Migration[7.0]
|
|
9
|
+
def change
|
|
10
|
+
rename_column :decidim_stratified_sortitions_substrata, :weighing, :max_quota_percentage
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Migration to create the panel_portfolios table for storing
|
|
4
|
+
# LEXIMIN-generated panels before sampling.
|
|
5
|
+
#
|
|
6
|
+
# This enables a two-phase sortition process:
|
|
7
|
+
# 1. Generate portfolio (expensive, can be done in background)
|
|
8
|
+
# 2. Sample from portfolio (fast, can be done publicly)
|
|
9
|
+
class CreatePanelPortfolios < ActiveRecord::Migration[7.0]
|
|
10
|
+
def change
|
|
11
|
+
create_table :decidim_stratified_sortitions_panel_portfolios do |t|
|
|
12
|
+
t.references :decidim_stratified_sortitions_stratified_sortition,
|
|
13
|
+
null: false,
|
|
14
|
+
foreign_key: { to_table: :decidim_stratified_sortitions_stratified_sortitions },
|
|
15
|
+
index: { name: "idx_panel_portfolios_on_sortition_id" }
|
|
16
|
+
|
|
17
|
+
# Panel data (JSON arrays)
|
|
18
|
+
# panels: [[id1, id2, ...], [id3, id4, ...], ...]
|
|
19
|
+
# probabilities: [0.3, 0.25, ...]
|
|
20
|
+
# selection_probabilities: { participant_id => probability, ... }
|
|
21
|
+
t.jsonb :panels, null: false, default: []
|
|
22
|
+
t.jsonb :probabilities, null: false, default: []
|
|
23
|
+
t.jsonb :selection_probabilities, null: false, default: {}
|
|
24
|
+
|
|
25
|
+
# Generation metadata
|
|
26
|
+
t.datetime :generated_at, null: false
|
|
27
|
+
t.float :generation_time_seconds
|
|
28
|
+
t.integer :num_iterations
|
|
29
|
+
t.boolean :convergence_achieved, null: false, default: false
|
|
30
|
+
|
|
31
|
+
# Sampling result (null until sampled)
|
|
32
|
+
t.integer :selected_panel_index
|
|
33
|
+
t.datetime :selected_at
|
|
34
|
+
t.string :verification_seed
|
|
35
|
+
t.float :random_value_used
|
|
36
|
+
|
|
37
|
+
t.timestamps
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Ensure only one portfolio per sortition
|
|
41
|
+
add_index :decidim_stratified_sortitions_panel_portfolios,
|
|
42
|
+
:decidim_stratified_sortitions_stratified_sortition_id,
|
|
43
|
+
unique: true,
|
|
44
|
+
name: "idx_panel_portfolios_unique_sortition"
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class AddForeignKeyToStratifiedSortitionsComponent < ActiveRecord::Migration[5.2]
|
|
4
|
+
def change
|
|
5
|
+
add_foreign_key :decidim_stratified_sortitions_stratified_sortitions,
|
|
6
|
+
:decidim_components,
|
|
7
|
+
column: :decidim_component_id,
|
|
8
|
+
on_delete: :cascade
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class AddCascadeToStratifiedSortitionsForeignKeys < ActiveRecord::Migration[7.0]
|
|
4
|
+
def change
|
|
5
|
+
add_foreign_key :decidim_stratified_sortitions_strata,
|
|
6
|
+
:decidim_stratified_sortitions_stratified_sortitions,
|
|
7
|
+
column: :decidim_stratified_sortition_id,
|
|
8
|
+
on_delete: :cascade
|
|
9
|
+
|
|
10
|
+
add_foreign_key :decidim_stratified_sortitions_substrata,
|
|
11
|
+
:decidim_stratified_sortitions_strata,
|
|
12
|
+
column: :decidim_stratified_sortitions_stratum_id,
|
|
13
|
+
on_delete: :cascade
|
|
14
|
+
|
|
15
|
+
remove_foreign_key :decidim_stratified_sortitions_sample_imports,
|
|
16
|
+
column: :stratified_sortition_id
|
|
17
|
+
add_foreign_key :decidim_stratified_sortitions_sample_imports,
|
|
18
|
+
:decidim_stratified_sortitions_stratified_sortitions,
|
|
19
|
+
column: :stratified_sortition_id,
|
|
20
|
+
on_delete: :cascade
|
|
21
|
+
|
|
22
|
+
remove_foreign_key :decidim_stratified_sortitions_sample_participants,
|
|
23
|
+
column: :decidim_stratified_sortition_id
|
|
24
|
+
add_foreign_key :decidim_stratified_sortitions_sample_participants,
|
|
25
|
+
:decidim_stratified_sortitions_stratified_sortitions,
|
|
26
|
+
column: :decidim_stratified_sortition_id,
|
|
27
|
+
on_delete: :cascade
|
|
28
|
+
|
|
29
|
+
remove_foreign_key :decidim_stratified_sortitions_sample_participants,
|
|
30
|
+
column: :decidim_stratified_sortitions_sample_import_id
|
|
31
|
+
add_foreign_key :decidim_stratified_sortitions_sample_participants,
|
|
32
|
+
:decidim_stratified_sortitions_sample_imports,
|
|
33
|
+
column: :decidim_stratified_sortitions_sample_import_id,
|
|
34
|
+
on_delete: :cascade
|
|
35
|
+
|
|
36
|
+
remove_foreign_key :decidim_stratified_sortitions_sample_participant_strata,
|
|
37
|
+
column: :decidim_stratified_sortitions_sample_participant_id
|
|
38
|
+
add_foreign_key :decidim_stratified_sortitions_sample_participant_strata,
|
|
39
|
+
:decidim_stratified_sortitions_sample_participants,
|
|
40
|
+
column: :decidim_stratified_sortitions_sample_participant_id,
|
|
41
|
+
on_delete: :cascade
|
|
42
|
+
|
|
43
|
+
remove_foreign_key :decidim_stratified_sortitions_sample_participant_strata,
|
|
44
|
+
column: :decidim_stratified_sortitions_stratum_id
|
|
45
|
+
add_foreign_key :decidim_stratified_sortitions_sample_participant_strata,
|
|
46
|
+
:decidim_stratified_sortitions_strata,
|
|
47
|
+
column: :decidim_stratified_sortitions_stratum_id,
|
|
48
|
+
on_delete: :cascade
|
|
49
|
+
|
|
50
|
+
remove_foreign_key :decidim_stratified_sortitions_sample_participant_strata,
|
|
51
|
+
column: :decidim_stratified_sortitions_substratum_id
|
|
52
|
+
add_foreign_key :decidim_stratified_sortitions_sample_participant_strata,
|
|
53
|
+
:decidim_stratified_sortitions_substrata,
|
|
54
|
+
column: :decidim_stratified_sortitions_substratum_id,
|
|
55
|
+
on_delete: :cascade
|
|
56
|
+
|
|
57
|
+
remove_foreign_key :decidim_stratified_sortitions_panel_portfolios,
|
|
58
|
+
column: :decidim_stratified_sortitions_stratified_sortition_id
|
|
59
|
+
add_foreign_key :decidim_stratified_sortitions_panel_portfolios,
|
|
60
|
+
:decidim_stratified_sortitions_stratified_sortitions,
|
|
61
|
+
column: :decidim_stratified_sortitions_stratified_sortition_id,
|
|
62
|
+
on_delete: :cascade
|
|
63
|
+
end
|
|
64
|
+
end
|