demographic 0.8.6.RKM.89602.beta.0
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/MIT-LICENSE +20 -0
- data/README.md +479 -0
- data/Rakefile +22 -0
- data/app/controllers/demographic/application_controller.rb +87 -0
- data/app/controllers/demographic/custom_parameter_values_controller.rb +25 -0
- data/app/controllers/demographic/optionals_bulk_controller.rb +33 -0
- data/app/controllers/demographic/optionals_controller.rb +68 -0
- data/app/controllers/demographic/optionals_types_controller.rb +17 -0
- data/app/controllers/demographic/user_optionals_controller.rb +12 -0
- data/app/jobs/demographic/application_job.rb +4 -0
- data/app/mailers/demographic/application_mailer.rb +6 -0
- data/app/serializers/demographic/optionals/filter_list_serializer.rb +34 -0
- data/app/serializers/demographic/optionals/list_serializer.rb +17 -0
- data/app/serializers/demographic/optionals/optional_serializer.rb +20 -0
- data/app/serializers/demographic/optionals/value_serializer.rb +5 -0
- data/app/services/demographic/custom_parameter_values/index.rb +53 -0
- data/app/services/demographic/helpers/association_localizer.rb +13 -0
- data/app/services/demographic/helpers/import/bulk/build_optionals.rb +54 -0
- data/app/services/demographic/helpers/import/bulk/create_optional_values.rb +32 -0
- data/app/services/demographic/helpers/import/bulk/create_or_update_user_optionals.rb +110 -0
- data/app/services/demographic/helpers/import/create_optionals_list.rb +60 -0
- data/app/services/demographic/helpers/import/create_or_update_custom_parameter_values.rb +97 -0
- data/app/services/demographic/helpers/import/create_or_update_user_values.rb +161 -0
- data/app/services/demographic/helpers/import/create_or_update_values.rb +124 -0
- data/app/services/demographic/optional_values/create_list.rb +61 -0
- data/app/services/demographic/optional_values/update_list.rb +85 -0
- data/app/services/demographic/optionals/bulk_create.rb +115 -0
- data/app/services/demographic/optionals/bulk_create_validations.rb +122 -0
- data/app/services/demographic/optionals/create.rb +90 -0
- data/app/services/demographic/optionals/list.rb +51 -0
- data/app/services/demographic/optionals/optional_values.rb +52 -0
- data/app/services/demographic/optionals/update.rb +100 -0
- data/app/services/demographic/parse/data_serializer.rb +87 -0
- data/app/services/demographic/parse/types/values.rb +99 -0
- data/app/services/demographic/user_optionals/list.rb +60 -0
- data/app/services/import/templates/create_optionals.rb +26 -0
- data/app/services/import/templates/xlsx.rb +44 -0
- data/config/initializers/custom_classes/string.rb +11 -0
- data/config/routes.rb +38 -0
- data/db/migrate/20201207181535_create_demographic_optionals.rb +18 -0
- data/db/migrate/20201207184210_create_users.rb +12 -0
- data/db/migrate/20201211204926_create_demographic_demographic_optional_values.rb +15 -0
- data/db/migrate/20201215193056_create_demographic_user_optional_values.rb +11 -0
- data/db/migrate/20220427163444_add_token_to_optionals.rb +6 -0
- data/db/migrate/20220427163507_add_token_to_optional_values.rb +6 -0
- data/lib/demographic/engine.rb +17 -0
- data/lib/demographic/version.rb +5 -0
- data/lib/demographic.rb +78 -0
- data/lib/generators/init/USAGE +8 -0
- data/lib/generators/init/init_generator.rb +11 -0
- data/lib/generators/init/templates/init_demographic.rb +14 -0
- data/lib/generators/init/templates/policy_demographic.rb +70 -0
- data/lib/generators/init_manual_update/USAGE +8 -0
- data/lib/generators/init_manual_update/init_manual_update_generator.rb +12 -0
- data/lib/generators/init_manual_update/templates/20220427163444_add_token_to_optionals.rb +6 -0
- data/lib/generators/init_manual_update/templates/20220427163507_add_token_to_optional_values.rb +6 -0
- data/lib/generators/init_manual_update/templates/demographic_update_tokens.rake +13 -0
- data/lib/generators/init_manual_update/templates/demographic_update_tokens_by_tenants.rake +24 -0
- data/lib/generators/init_manual_update_v2/init_manual_update_generator.rb +10 -0
- data/lib/generators/init_manual_update_v2/templates/20240206120304_create_custom_parameter_values.rb +10 -0
- data/lib/generators/init_manual_update_v2/templates/custom_parameter_value.rb +5 -0
- data/lib/generators/init_model/USAGE +8 -0
- data/lib/generators/init_model/init_model_generator.rb +12 -0
- data/lib/generators/init_model/templates/optional.rb +5 -0
- data/lib/generators/init_model/templates/optional_value.rb +4 -0
- data/lib/generators/init_model/templates/user.rb +5 -0
- data/lib/generators/init_model/templates/user_optional.rb +5 -0
- data/lib/tasks/demographic_tasks.rake +4 -0
- metadata +346 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: c0c4c96874175a3b508170ae59787fa3caaeab6f0e89047d9fe25d60da7e5058
|
|
4
|
+
data.tar.gz: 12c3c0acf0a5c2140de1229d1d9197e4a955ab385bbe07680d783209e915e3e4
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 4af1830835024b8bda5ecaa75028f2d990951fd3d982bffc18dbc49ef2e8087587b5d32f0b109f31689f24350f6efdb6822650e34d44812bdd57dfa74f74e408
|
|
7
|
+
data.tar.gz: c370e1bda98ea8045f0f70cb0091a2230da46fa69e67cfc3d5e1995b50e605be4cb7cdb888b03834ff91ebd3dfd3e849b54ac74603a4918bebdbb970dc2895a9
|
data/MIT-LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright 2020 jrojasetiner
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
4
|
+
a copy of this software and associated documentation files (the
|
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
9
|
+
the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be
|
|
12
|
+
included in all copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,479 @@
|
|
|
1
|
+
# Demographic
|
|
2
|
+
|
|
3
|
+
Es un motor de rails que permite agregar atributos demograficos por tipos a los usuarios y luego ser usados para su
|
|
4
|
+
respectivo filtro
|
|
5
|
+
|
|
6
|
+
### Documentacion para la creacion y carga
|
|
7
|
+
|
|
8
|
+
https://intercom.help/rankmi/es/articles/5345051-creacion-carga-y-actualizacion-de-opcionales
|
|
9
|
+
|
|
10
|
+
## Instalación
|
|
11
|
+
|
|
12
|
+
seguir cada paso:
|
|
13
|
+
|
|
14
|
+
```ruby
|
|
15
|
+
gem 'demographic'
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
And then execute:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
$ bundle
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Or install it yourself as:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
$ gem install demographic
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Genera el setting para los tipos de octionales, la seguridad
|
|
31
|
+
y genera los modelos a usar en el proyecto.
|
|
32
|
+
|
|
33
|
+
Se agregan los archivos de config
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
rails g init demographic
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
- config/initializers/init_demographic.rb
|
|
40
|
+
- app/middleware/policy_demographic.rb
|
|
41
|
+
|
|
42
|
+
Se agregan los siguientes modelos (solo si desea trabajar con ellos)
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
rails g init_model demographic
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
- users
|
|
49
|
+
- optionals
|
|
50
|
+
- optional_values
|
|
51
|
+
- user_optionals
|
|
52
|
+
|
|
53
|
+
Config migraciones: copia las migraciones al proyecto (solo si desea trabajar con ellos)
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
rake demographic:install:migrations
|
|
57
|
+
rake db:migrate
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Nota:
|
|
61
|
+
|
|
62
|
+
* Para relacionar el modelo padre con optionals se debe
|
|
63
|
+
agregar la siguiente linea solo si usas los modelos del motor
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
has_many :optionals, as: :adjustable
|
|
67
|
+
|
|
68
|
+
Ejemplo:
|
|
69
|
+
class Survey < ApplicationRecord
|
|
70
|
+
has_many :optionals, as: :adjustable
|
|
71
|
+
end
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
ACTUALIZACIÓN:
|
|
75
|
+
|
|
76
|
+
* En el caso de los proyectos que ya implementan el engine, para agregar el campo "token"
|
|
77
|
+
en Optionals y OptionalValues, se debe de ejeuctar el siguiente comando
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
rails g init_manual_update demographic
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Corre las migraciones
|
|
84
|
+
|
|
85
|
+
* Si se produce algun error ArgumentError: Unknown migration version "6.0";
|
|
86
|
+
de version solo basta con cambiarla en los migrates a la version correspondiente
|
|
87
|
+
|
|
88
|
+
```
|
|
89
|
+
rake db:migrate
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Actualizar tokens en Optionals y OptionalsValues
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
rake demographic:update_tokens
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
En el caso de proyectos como Rankmi Forms, el cual implementa multiples tenants, se
|
|
99
|
+
debe de ejecutar el siguiente comando en lugar del anterior
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
rake demographic:update_tokens_by_tenants
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Config rutas: agregar en el routes.rb
|
|
106
|
+
(el adjustable_id es el id del survey, process o empresa)
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
mount Demographic::Engine => "/demographic"
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Parametros de las rutas:
|
|
113
|
+
|
|
114
|
+
- module: puede ser (performance, engagement, talent, csi ...)
|
|
115
|
+
- adjustable_id: (process_id, survey_id) el id al que pertenece el o los opcionales
|
|
116
|
+
|
|
117
|
+
EPs:
|
|
118
|
+
|
|
119
|
+
- GET demographic/optionalTypes
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
{
|
|
123
|
+
"types": [
|
|
124
|
+
"checkbox",
|
|
125
|
+
"radio",
|
|
126
|
+
"list",
|
|
127
|
+
"text",
|
|
128
|
+
"date",
|
|
129
|
+
"number",
|
|
130
|
+
"boolean"
|
|
131
|
+
]
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
- GET demographic/:module/optionals/list/:adjustable_id?page=1&term='optional'
|
|
136
|
+
|
|
137
|
+
```
|
|
138
|
+
{
|
|
139
|
+
"limit_value": 20,
|
|
140
|
+
"current_page": 1,
|
|
141
|
+
"total_pages": 2,
|
|
142
|
+
"total_objects": 30,
|
|
143
|
+
"optionals": [
|
|
144
|
+
{
|
|
145
|
+
"key": id,
|
|
146
|
+
"id": 61,
|
|
147
|
+
"code": "twyla",
|
|
148
|
+
"name_translate": {
|
|
149
|
+
"es": "Twyla"
|
|
150
|
+
},
|
|
151
|
+
"input_type": "text",
|
|
152
|
+
"created_at": "11-12-2020",
|
|
153
|
+
"module": "position"
|
|
154
|
+
}]
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
- POST demographic/:module/optionals/create/:adjustable_id
|
|
159
|
+
|
|
160
|
+
```
|
|
161
|
+
body:
|
|
162
|
+
|
|
163
|
+
{
|
|
164
|
+
'optional': {
|
|
165
|
+
'name_translate': {es: '', en: ''},
|
|
166
|
+
'input_type': types.sample(random: SecureRandom),
|
|
167
|
+
'min_value': '',
|
|
168
|
+
'max_value': '',
|
|
169
|
+
'values': [
|
|
170
|
+
{'order_num': 1, 'value_translate': {es: '', en: ''} },
|
|
171
|
+
{'order_num': 2, 'value_translate': {es: '', en: ''} },
|
|
172
|
+
{'order_num': 3, 'value_translate': {es: '', en: ''} },
|
|
173
|
+
],
|
|
174
|
+
code: 'optional_code
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
response 200:
|
|
179
|
+
|
|
180
|
+
{
|
|
181
|
+
'optional': {
|
|
182
|
+
'id': 0,
|
|
183
|
+
'name_translate': {es: '', en: ''},
|
|
184
|
+
'input_type': types.sample(random: SecureRandom),
|
|
185
|
+
'min_value': '',
|
|
186
|
+
'max_value': '',
|
|
187
|
+
'values': [
|
|
188
|
+
{'id': 0, order_num': 1, 'value_translate': {es: '', en: ''} },
|
|
189
|
+
{'id': 0,'order_num': 2, 'value_translate': {es: '', en: ''} },
|
|
190
|
+
{'id': 0,'order_num': 3, 'value_translate': {es: '', en: ''} },
|
|
191
|
+
],
|
|
192
|
+
'module': 'enterprise',
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
response 404 / 422:
|
|
197
|
+
{ success: false, message: '' }
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
- DELETE demographic/:module/optionals/:optional_id/update/:adjustable_id
|
|
201
|
+
|
|
202
|
+
```
|
|
203
|
+
response 200:
|
|
204
|
+
{ success: true }
|
|
205
|
+
|
|
206
|
+
response 404 / 422:
|
|
207
|
+
{ success: false, message: '' }
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
- GET demographic/:module/optionals/:optional_id/show/:adjustable_id
|
|
211
|
+
|
|
212
|
+
```
|
|
213
|
+
response 200:
|
|
214
|
+
{
|
|
215
|
+
'optional': {
|
|
216
|
+
'id': 0,
|
|
217
|
+
'name_translate': {es: '', en: ''},
|
|
218
|
+
'input_type': types.sample(random: SecureRandom),
|
|
219
|
+
'min_value': '',
|
|
220
|
+
'max_value': '',
|
|
221
|
+
'values': [
|
|
222
|
+
{'id': 0, order_num': 1, 'value_translate': {es: '', en: ''} },
|
|
223
|
+
{'id': 0,'order_num': 2, 'value_translate': {es: '', en: ''} },
|
|
224
|
+
{'id': 0,'order_num': 3, 'value_translate': {es: '', en: ''} },
|
|
225
|
+
]
|
|
226
|
+
'module': 'enterprise',
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
response 404 / 422:
|
|
231
|
+
{ success: false, message: '' }
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
- PUT demographic/:module/optionals/:optional_id/update/:adjustable_id
|
|
235
|
+
|
|
236
|
+
```
|
|
237
|
+
response 200:
|
|
238
|
+
{
|
|
239
|
+
'optional': {
|
|
240
|
+
'id': 0,
|
|
241
|
+
'name_translate': {es: '', en: ''},
|
|
242
|
+
'input_type': types.sample(random: SecureRandom),
|
|
243
|
+
'min_value': '',
|
|
244
|
+
'max_value': '',
|
|
245
|
+
'values': [
|
|
246
|
+
{'id': 0, order_num': 1, 'value_translate': {es: '', en: ''} },
|
|
247
|
+
{'id': 0,'order_num': 2, 'value_translate': {es: '', en: ''} },
|
|
248
|
+
{'id': 0,'order_num': 3, 'value_translate': {es: '', en: ''} },
|
|
249
|
+
],
|
|
250
|
+
'module': 'enterprise',
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
- GET demographic/:module/userOptionals/list/:adjustable_id?user_token=
|
|
255
|
+
- Nota: puede enviar el id o el token del usuario en el parametro user_token
|
|
256
|
+
|
|
257
|
+
```
|
|
258
|
+
response 200:
|
|
259
|
+
{
|
|
260
|
+
optionals: [
|
|
261
|
+
{
|
|
262
|
+
id: optional.id,
|
|
263
|
+
code: optional.code,
|
|
264
|
+
name: optional.name,
|
|
265
|
+
input_type: optional.input_type,
|
|
266
|
+
selected_text: 'texto o valor campos libres',
|
|
267
|
+
values: [
|
|
268
|
+
{
|
|
269
|
+
id: value.id,
|
|
270
|
+
slug: value.slug,
|
|
271
|
+
code: value.code,
|
|
272
|
+
value: value.value,
|
|
273
|
+
selected: true / false
|
|
274
|
+
}, ...
|
|
275
|
+
]
|
|
276
|
+
}, ...
|
|
277
|
+
],
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
response 404 / 422:
|
|
281
|
+
{ success: false, message: '' }
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
- GET demographic/:module/optionals/filterList/:adjustable_id
|
|
285
|
+
|
|
286
|
+
```
|
|
287
|
+
response 200:
|
|
288
|
+
{
|
|
289
|
+
optionals: [
|
|
290
|
+
{
|
|
291
|
+
label: optional.name,
|
|
292
|
+
value: optional.id,
|
|
293
|
+
type: optional.input_type,
|
|
294
|
+
list: [
|
|
295
|
+
{
|
|
296
|
+
label: value.value
|
|
297
|
+
value: value.id,
|
|
298
|
+
}, ...
|
|
299
|
+
]
|
|
300
|
+
}, ...
|
|
301
|
+
]
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
response 404 / 422:
|
|
305
|
+
{ success: false, message: '' }
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
GET demographic/optionals/options
|
|
309
|
+
|
|
310
|
+
```
|
|
311
|
+
response 200:
|
|
312
|
+
{
|
|
313
|
+
"master":"Users","position":"Positions"
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
## Helpers
|
|
319
|
+
|
|
320
|
+
### Tipos de opcionales
|
|
321
|
+
|
|
322
|
+
| Tipo de Opcional | Descripción | Ejemplo |
|
|
323
|
+
| --- | --- |--------------|
|
|
324
|
+
| list | Acepta cualquier formato, excepto vacío | "naranja" |
|
|
325
|
+
| text | Acepta cualquier formato, excepto vacío | "Hola mundo" |
|
|
326
|
+
| number | Acepta cualquier número, excepto vacío | 42 |
|
|
327
|
+
| date | Acepta estos formatos: %d-%m-%Y %d/%m/%Y %Y-%m-%d %Y/%m/%d, excepto vacío | "01-01-2022" |
|
|
328
|
+
| bool | Acepta 0 y 1 | 1 |
|
|
329
|
+
|
|
330
|
+
- crea los optionals
|
|
331
|
+
|
|
332
|
+
```
|
|
333
|
+
file_headers = ["optional_lista#list", "optional_numerico#num", "optional_fecha#date"]
|
|
334
|
+
|
|
335
|
+
reference_id = id del modelo a buscar (survey.id, process.id, etc)
|
|
336
|
+
parent_module = referencia al producto (:performance, :engagement, etc)
|
|
337
|
+
|
|
338
|
+
::Demographic::Helpers::Import::CreateOptionalsList.call(file_headers: file_headers,
|
|
339
|
+
parent_module: :engagement,
|
|
340
|
+
reference_id: survey.id)
|
|
341
|
+
|
|
342
|
+
caso ok: { success: true, message: 'Success!!!' }
|
|
343
|
+
caso error: { success: false, message: 'mensaje con el error' }
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
- crea valores de los opcionales
|
|
347
|
+
|
|
348
|
+
```
|
|
349
|
+
optionals = { "optional_fecha#date": "1988-09-27",
|
|
350
|
+
"optional_lista#list": "test 1",
|
|
351
|
+
"optional_numerico#num": "1"}
|
|
352
|
+
|
|
353
|
+
reference_id = id del modelo a buscar (survey.id, process.id, etc)
|
|
354
|
+
parent_module = referencia al producto (:performance, :engagement, etc)
|
|
355
|
+
|
|
356
|
+
Demographic::Helpers::CreateOrUpdateValues.call(optionals:, parent_module:, reference_id:)
|
|
357
|
+
|
|
358
|
+
caso ok: { success: true, message: 'Success!!!', optionals: [{optional_id:'',optional_value_id: '', value: ''}] }
|
|
359
|
+
caso error: { success: false, message: 'mensaje con el error', optionals: [] }
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
- asignar valores en los usuarios, recibe un objeto user y un hash con los opcionales
|
|
363
|
+
|
|
364
|
+
```
|
|
365
|
+
optionals = [
|
|
366
|
+
{ optional_id, optional_value_id, value }, ...
|
|
367
|
+
]
|
|
368
|
+
|
|
369
|
+
reference_id = id del modelo a buscar (survey.id, process.id, etc)
|
|
370
|
+
parent_module = referencia al producto (:performance, :engagement, etc)
|
|
371
|
+
|
|
372
|
+
Demographic::Helpers::CreateOrUpdateUserValues.call(user:, optionals:, parent_module:, reference_id:)
|
|
373
|
+
|
|
374
|
+
caso ok: { success: true, message: 'Success!!!', optionals: [{optional_id:'', optional_user_id: '',optional_value_id: ''}] }
|
|
375
|
+
caso error: { success: false, message: 'mensaje con el error', optionals: [] }
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
- `Demographic::Helpers::Import::Bulk::BuildOptionals`: Este servicio se encarga de la creacion de `OptionalValue` y
|
|
379
|
+
`UserOptional` de manera masiva a traves de la data extraida previamente por un excel de opcionales. El servicio
|
|
380
|
+
tambien se encarga de validar que los datos sean correctos y que no existan duplicados. En caso de no ser
|
|
381
|
+
correctos, se hace skip del item. Tambien se encarga de validar que los usuarios tengan relacion con el adjustable
|
|
382
|
+
para evitar modifcar usuarios pertenecientes a otros adjustables, esto siempre y cuando exista una relacion con
|
|
383
|
+
`users` desde ese adjustable, si no existe dicha relacion, se busca desde todos los usuarios, por lo que se
|
|
384
|
+
tendrian que validar los usarios antes de enviarlos a este servicio.
|
|
385
|
+
<br/>
|
|
386
|
+
<br/>
|
|
387
|
+
- Parametros: Para instanciar este servicio, se necesitará:
|
|
388
|
+
1. `parent_module`: Es el módulo en el que se esta ejecuntando el servicio, por ejemplo: `'performance'`,
|
|
389
|
+
`'engaament'`
|
|
390
|
+
2. `reference_id`: El id del modelo al que se le asignarán los opcionales. Este modelo cambiará según el
|
|
391
|
+
`parent_module`
|
|
392
|
+
3. `users_data`: Estructura que viene de los excels, por ejemplo:
|
|
393
|
+
```ruby
|
|
394
|
+
[
|
|
395
|
+
{
|
|
396
|
+
"token": "hgsi1323",
|
|
397
|
+
"optional_fecha": "2023-05-31",
|
|
398
|
+
"optional_lista": "test 1",
|
|
399
|
+
"optional_numerico": "1"
|
|
400
|
+
},
|
|
401
|
+
{
|
|
402
|
+
"token": "hgsi1323",
|
|
403
|
+
"optional_fecha": "2023-05-31",
|
|
404
|
+
"optional_lista": "test 1",
|
|
405
|
+
"optional_numerico": "1"
|
|
406
|
+
}
|
|
407
|
+
]
|
|
408
|
+
```
|
|
409
|
+
- Respuesta: Siempre va a retornar una estructura de este tipo: `Struct.new(:success, :message)`
|
|
410
|
+
<br/>
|
|
411
|
+
<br/>
|
|
412
|
+
- Cuando no hay error:
|
|
413
|
+
```ruby
|
|
414
|
+
#<struct success=true, message="">
|
|
415
|
+
```
|
|
416
|
+
- Cuando hay error:
|
|
417
|
+
```ruby
|
|
418
|
+
#<struct success=false, message=#<RuntimeError: Error message>>
|
|
419
|
+
```
|
|
420
|
+
- Uso:
|
|
421
|
+
```ruby
|
|
422
|
+
parent_module = 'performance'
|
|
423
|
+
reference_id = 1
|
|
424
|
+
users_data = [{ "token" => "7939511-0-150",
|
|
425
|
+
"optional_lajuana" => "0_5709e2c973",
|
|
426
|
+
"optional_elaine" => "1_d373ecf4fa",
|
|
427
|
+
"optional_elsy" => "2_7199378ff3",
|
|
428
|
+
"optional_sheilah" => "3_f92cee5eb2",
|
|
429
|
+
"optional_monty" => "4_a6e231e928" },
|
|
430
|
+
{ "token" => "21579056-8-26",
|
|
431
|
+
"optional_lajuana" => "0_cf64882943",
|
|
432
|
+
"optional_elaine" => "1_fd86709937",
|
|
433
|
+
"optional_elsy" => "2_739f413c42",
|
|
434
|
+
"optional_sheilah" => "3_9a9853e0b9",
|
|
435
|
+
"optional_monty" => "4_218f8ef272" }]
|
|
436
|
+
|
|
437
|
+
::Demographic::Helpers::Import::Bulk::BuildOptionals.new(parent_module: parent_module,
|
|
438
|
+
reference_id: reference_id,
|
|
439
|
+
users_data: users_data).call
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
## Correr los test
|
|
443
|
+
|
|
444
|
+
ejecutar
|
|
445
|
+
|
|
446
|
+
```
|
|
447
|
+
rspec ./spec/requests
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
## Publicando la gema:
|
|
451
|
+
|
|
452
|
+
Es importante asegurarse que al momento de ejecutar el comando gem push, se realice modificando el tagueo con la version
|
|
453
|
+
recien generada luego del gembuild
|
|
454
|
+
|
|
455
|
+
ejecutar
|
|
456
|
+
|
|
457
|
+
```
|
|
458
|
+
gem build demographic.gemspec
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
el cual resultara en una salida del tipo:
|
|
462
|
+
` Successfully built RubyGem
|
|
463
|
+
Name: demographic
|
|
464
|
+
Version: 0.1.3
|
|
465
|
+
File: demographic-0.1.3.gem
|
|
466
|
+
`
|
|
467
|
+
La publicacion debe hacerse con la version indiciada en el paso anterior(0.1.1)
|
|
468
|
+
|
|
469
|
+
```
|
|
470
|
+
gem push --key github --host https://rubygems.pkg.github.com/Rankmi demographic-0.1.1.gem
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
## Contributing
|
|
474
|
+
|
|
475
|
+
Contribution directions go here.
|
|
476
|
+
|
|
477
|
+
## License
|
|
478
|
+
|
|
479
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
begin
|
|
2
|
+
require 'bundler/setup'
|
|
3
|
+
rescue LoadError
|
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
require 'rdoc/task'
|
|
8
|
+
|
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
|
11
|
+
rdoc.title = 'Demographic'
|
|
12
|
+
rdoc.options << '--line-numbers'
|
|
13
|
+
rdoc.rdoc_files.include('README.md')
|
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
APP_RAKEFILE = File.expand_path("spec/dummy/Rakefile", __dir__)
|
|
18
|
+
load 'rails/tasks/engine.rake'
|
|
19
|
+
|
|
20
|
+
load 'rails/tasks/statistics.rake'
|
|
21
|
+
|
|
22
|
+
require 'bundler/gem_tasks'
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Demographic
|
|
4
|
+
class ApplicationController < ActionController::API
|
|
5
|
+
# protect_from_forgery with: :exception
|
|
6
|
+
before_action :has_config?
|
|
7
|
+
|
|
8
|
+
rescue_from NoMethodError, with: :not_method_error
|
|
9
|
+
rescue_from ActiveRecord::RecordNotFound, with: :not_found
|
|
10
|
+
rescue_from ActiveRecord::RecordInvalid, with: :record_invalid
|
|
11
|
+
rescue_from ActiveRecord::RecordNotUnique, with: :not_found
|
|
12
|
+
|
|
13
|
+
private
|
|
14
|
+
|
|
15
|
+
def has_config?
|
|
16
|
+
Demographic.attributes.each do |attr|
|
|
17
|
+
raise NoMethodError, "init Demographic.#{attr} error!!!" unless Demographic.send(attr).present?
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
i18n_setup
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def not_method_error(invalid)
|
|
24
|
+
render json: { success: false, message: invalid.to_s }, status: 404
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def not_found(invalid)
|
|
28
|
+
render json: { success: false, message: invalid.to_s }, status: :not_found
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def record_invalid(invalid)
|
|
32
|
+
render json: { success: false, message: invalid.record.errors.messages }, status: :unprocessable_entity
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def adjustable
|
|
36
|
+
parent_model = Demographic.parent_model[params[:module]&.to_sym]
|
|
37
|
+
|
|
38
|
+
return if parent_model.blank?
|
|
39
|
+
|
|
40
|
+
model_class = parent_model.to_s.capitalize.classify.constantize
|
|
41
|
+
|
|
42
|
+
if params[:adjustable_id] == "0"
|
|
43
|
+
#non-persisted object to avoid errors downstream
|
|
44
|
+
return @adjustable = model_class.new(id: 0)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
@adjustable = model_class.find_by!(id: params[:adjustable_id])
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def optional
|
|
51
|
+
@optional ||= Optional.find!(params[:optional_id])
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def user
|
|
55
|
+
return @user if @user.present?
|
|
56
|
+
|
|
57
|
+
if params[:user_token].present?
|
|
58
|
+
raise ActiveRecord::RecordNotFound, 'User not found' unless User.new.attributes.key?('token')
|
|
59
|
+
|
|
60
|
+
@user = User.find_by!(token: params[:user_token])
|
|
61
|
+
return @user
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
@user = User.find(params[:user_id])
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def optional_adjustable
|
|
68
|
+
@optional_adjustable ||= params[:optional_token].present? ? Optional.find_by!(token: params[:optional_token]) : Optional.find_by!(id: params[:optional_id])
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def i18n_setup
|
|
72
|
+
return I18n.locale unless request.headers['Authorization'].present?
|
|
73
|
+
|
|
74
|
+
token = request.headers['Authorization'].split(' ')[1]
|
|
75
|
+
decode = JWT.decode(token, Demographic.jwt_password, true, { algorithm: 'HS256'} )
|
|
76
|
+
return I18n.locale unless decode.present?
|
|
77
|
+
RequestStore.store[:jwt] = decode[0]
|
|
78
|
+
I18n.locale = decode[0]['lang']&.to_sym || :es
|
|
79
|
+
rescue JWT::DecodeError, JWT::ExpiredSignature, StandardError
|
|
80
|
+
I18n.locale
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def per_page
|
|
84
|
+
@per_page ||= params[:per_page].present? ? params[:per_page].to_i : Demographic.per_page.present? ? Demographic.per_page.to_i : 20
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
require_dependency "demographic/application_controller"
|
|
2
|
+
|
|
3
|
+
module Demographic
|
|
4
|
+
class CustomParameterValuesController < ApplicationController
|
|
5
|
+
# record passed should have a token uuid!
|
|
6
|
+
# GET demographic/:module/customParameterValues/index/:adjustable_id?record_token=
|
|
7
|
+
def index
|
|
8
|
+
render json: Demographic::CustomParameterValues::Index.new(record: record, adjustable: adjustable, page: params[:page], per_page: per_page).call, status: :ok
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def create
|
|
12
|
+
service = Demographic::CustomParameterValues::Create.new(record: record, adjustable: adjustable, params: create_params)
|
|
13
|
+
render json: service.call, status: :created
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
def create_params
|
|
18
|
+
params.require(:custom_parameter_values).permit(:optional_id, :value)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def record
|
|
22
|
+
@record = adjustable.class.find_by_token!(params[:record_token])
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
require_dependency "demographic/application_controller"
|
|
2
|
+
|
|
3
|
+
module Demographic
|
|
4
|
+
class OptionalsBulkController < ApplicationController
|
|
5
|
+
# POST /:module/optionals_bulk/:adjustable_id/create
|
|
6
|
+
def create
|
|
7
|
+
response = bulk_create_service.call
|
|
8
|
+
|
|
9
|
+
render json: response.data, status: response.status
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# GET /:module/optionals_bulk/:adjustable_id/create_template
|
|
13
|
+
def create_template
|
|
14
|
+
xlsx_file = template_service.call
|
|
15
|
+
|
|
16
|
+
send_file xlsx_file.path, filename: template_class::FILE_NAME, disposition: 'attachment'
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
def bulk_create_service
|
|
22
|
+
@bulk_create_service ||= ::Demographic::Optionals::BulkCreate.new(file: params[:file], adjustable: adjustable)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def template_service
|
|
26
|
+
@template_service ||= template_class.new
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def template_class
|
|
30
|
+
@template_class ||= Import::Templates::CreateOptionals
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|