Skip to content

Commit

Permalink
Merge branch 'staging' into 895
Browse files Browse the repository at this point in the history
  • Loading branch information
alemangui committed Aug 27, 2024
2 parents 350acfb + ac385d5 commit c9ac3f5
Show file tree
Hide file tree
Showing 20 changed files with 233 additions and 30 deletions.
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ SENTRY_DSN (optionnel)= Le Data Source Name pour Sentry. Peut être vide.
MATOMO_ID (optionnel)= L'ID pour le suivi avec Matomo. Compl-alim utilise l'ID 95 pour la prod, en local c'est mieux de le laisser vide
REDIS_URL= L'instance redis à utiliser pour les tâches asynchrones et le cache des clés API. Par exemple : 'redis://localhost:6379/0'
REDIS_PREPEND_KEY= Optionnel - Ajout ce string au début de chaque clé Redis. Utile pour partager la même DB Redis sur plusieurs environnements
S3CFG_FILE_URI= Optionnel - Url de téléchargement du fichier de config s3cmd
```

#### Créer les différents modèles Django dans la base de données
Expand Down Expand Up @@ -185,3 +186,14 @@ Vous pouvez aussi charger des éléments (ingrédients, substances, etc.) dans l
```
python manage.py load_ingredients
```

## Envoi des données au bucket s3 pour récupération par les serveurs

Telecharger le fichier s3cfg correspondant au bucket
```
s3cmd setpolicy ./clevercloud/allow_policy.json s3://csv-data
s3cmd put <data_directory> s3://csv-data --recursive
s3cmd setpolicy ./clevercloud/deny_policy.json s3://csv-data
```

Les serveurs d'env prod/staging/demo utilisent le script clevercloud/post_build_hook.sh pour la récupération des données
2 changes: 2 additions & 0 deletions api/serializers/declaration.py
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,8 @@ class Meta:
"computed_substances",
"attachments",
"other_effects",
"other_galenic_formulation",
"other_conditions",
"instructor",
"visor",
"post_validation_status",
Expand Down
17 changes: 17 additions & 0 deletions clevercloud/allow_policy.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"Id": "Policy1587216857769",
"Statement": [
{
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:ListBucket"
],
"Effect": "Allow",
"Principal": "*",
"Resource": "arn:aws:s3:::csv-data/*",
"Sid": "Stmt1587216727444"
}
],
"Version": "2012-10-17"
}
15 changes: 15 additions & 0 deletions clevercloud/deny_policy.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"Id": "Policy1587216857769",
"Statement": [
{
"Action": [
"*"
],
"Effect": "Deny",
"Principal": "*",
"Resource": "arn:aws:s3:::csv-data/*",
"Sid": "Stmt1587216727444"
}
],
"Version": "2012-10-17"
}
15 changes: 15 additions & 0 deletions clevercloud/run_succeeded_hook.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
curl $S3CFG_FILE_URI > .s3cfg
# retrieve most recent date
FILEPATH=$(s3cmd ls s3://csv-data| tail -1 | awk '{ print $2 }')
DATE=${FILEPATH##"s3://csv-data/"}
DATE=${DATE%"/"}
# if this date doesn't exist yet
if ls csv-data/$DATE ; then
echo "This data has already been loaded"
else
# retrieve most recent files
mkdir -p csv-data/$DATE/
s3cmd get s3://csv-data/$DATE/ --recursive csv-data/$DATE/
# import those files to database (django models)
python $APP_ID/manage.py load_ingredients -d csv-data/$DATE $DATE
fi
12 changes: 7 additions & 5 deletions data/csv_importer.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

# Import the model
from .models import (
Condition,
Effect,
GalenicFormulation,
Ingredient,
Expand All @@ -32,8 +33,6 @@
SubstanceSynonym,
SubstanceUnit,
)

# from .models.condition import Condition
from .utils.importer_utils import get_update_or_create_related_object, pre_import_treatments, update_or_create_object

logger = logging.getLogger(__name__)
Expand All @@ -46,7 +45,8 @@
"REF_ICA_PLANTE.csv": Plant,
"REF_ICA_FAMILLE_PLANTE.csv": PlantFamily,
"REF_ICA_SUBSTANCE_ACTIVE.csv": Substance,
"POPULATION.csv": Population,
"POPULATION_CIBLE.csv": Population,
"REF_ICA_POPULATION_ARISQUE.csv": Condition,
"REF_ICA_OBJECTIFS_EFFETS.csv": Effect,
"REF_ICA_FORME_GALENIQUE.csv": GalenicFormulation,
"REF_ICA_UNITE.csv": SubstanceUnit,
Expand Down Expand Up @@ -86,12 +86,13 @@ class CSVImporter:
"FRMGAL": GalenicFormulation,
"TYPPREP": Preparation,
"STINGSBS": IngredientStatus,
"POPRS": Condition,
"": Population,
# Pour les tables de relation on garde le prefix correspondant au modèle dans lequel les données vont être importées
# "REF_ICA_AUTREING_SUBSTACTIVE.csv": "INGA",
# "REF_ICA_PLANTE_SUBSTANCE.csv": "PLTE",
# "REF_ICA_PARTIE_PL_A_SURVEILLER.csv": "",
# "REF_ICA_PARTIE_UTILE.csv": "",
# "POPULATION.csv": "",
}

# Établi les suffix des champ des csv correspondant aux champs des modèles Django
Expand Down Expand Up @@ -121,6 +122,7 @@ class CSVImporter:
"min_age": ["AGE_MIN"],
"max_age": ["AGE_MAX"],
"is_defined_by_anses": ["CATEGORIE_ANSES"],
"is_liquid": ["LIQUIDE"],
# Les champs ForeignKey (synonymes)
"standard_name": ["SBSACT_IDENT", "PLTE_IDENT", "INGA_IDENT", "MORG_IDENT"],
"siccrf_family": ["FAMPL_IDENT"],
Expand All @@ -141,7 +143,7 @@ class CSVImporter:
"missing_import_data",
"to_be_entered_in_next_decree",
]
NEW_FIELDS = ["is_liquid", "long_name"]
NEW_FIELDS = ["long_name"]

def __init__(self, file, model, is_relation=False, mapping=None):
"""Initialise un CSVImporter avec le fichier source, le modèle de destination, etc
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Generated by Django 5.1 on 2024-08-21 16:05

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
("data", "0085_companyaccessclaim_declarant_role_and_more"),
]

operations = [
migrations.AlterModelOptions(
name="effect",
options={
"verbose_name": "Objectif et effet des compléments alimentaires",
"verbose_name_plural": "Objectifs et effets des compléments alimentaires",
},
),
migrations.AlterModelOptions(
name="historicaleffect",
options={
"get_latest_by": ("history_date", "history_id"),
"ordering": ("-history_date", "-history_id"),
"verbose_name": "historical Objectif et effet des compléments alimentaires",
"verbose_name_plural": "historical Objectifs et effets des compléments alimentaires",
},
),
migrations.AlterModelOptions(
name="historicalpopulation",
options={
"get_latest_by": ("history_date", "history_id"),
"ordering": ("-history_date", "-history_id"),
"verbose_name": "historical Population cible",
"verbose_name_plural": "historical Populations cibles",
},
),
migrations.AlterModelOptions(
name="population",
options={
"verbose_name": "Population cible",
"verbose_name_plural": "Populations cibles",
},
),
]
57 changes: 57 additions & 0 deletions data/migrations/0087_declaration_other_conditions_and_more.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Generated by Django 5.1 on 2024-08-22 08:56

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("data", "0086_alter_effect_options_alter_historicaleffect_options_and_more"),
]

operations = [
migrations.AddField(
model_name="declaration",
name="other_conditions",
field=models.TextField(
blank=True,
verbose_name="autres populations à risques ou facteurs de risques non listés",
),
),
migrations.AddField(
model_name="declaration",
name="other_galenic_formulation",
field=models.TextField(
blank=True, verbose_name="autre forme galénique non listée"
),
),
migrations.AddField(
model_name="historicaldeclaration",
name="other_conditions",
field=models.TextField(
blank=True,
verbose_name="autres populations à risques ou facteurs de risques non listés",
),
),
migrations.AddField(
model_name="historicaldeclaration",
name="other_galenic_formulation",
field=models.TextField(
blank=True, verbose_name="autre forme galénique non listée"
),
),
migrations.AlterField(
model_name="declaration",
name="other_effects",
field=models.TextField(
blank=True, verbose_name="autres objectifs ou effets non listés"
),
),
migrations.AlterField(
model_name="historicaldeclaration",
name="other_effects",
field=models.TextField(
blank=True, verbose_name="autres objectifs ou effets non listés"
),
),
]
6 changes: 5 additions & 1 deletion data/models/declaration.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ class RejectionReason(models.TextChoices):
galenic_formulation = models.ForeignKey(
GalenicFormulation, verbose_name="forme galénique", null=True, blank=True, on_delete=models.RESTRICT
)
other_galenic_formulation = models.TextField(blank=True, verbose_name="autre forme galénique non listée")

unit_quantity = models.FloatField(
null=True, blank=True, verbose_name="poids ou volume d'une unité de consommation"
Expand All @@ -144,9 +145,12 @@ class RejectionReason(models.TextChoices):
conditions_not_recommended = models.ManyToManyField(
Condition, blank=True, verbose_name="consommation déconseillée"
)
other_conditions = models.TextField(
blank=True, verbose_name="autres populations à risques ou facteurs de risques non listés"
)

effects = models.ManyToManyField(Effect, blank=True, verbose_name="objectifs ou effets")
other_effects = models.TextField(blank=True, verbose_name="autres objectifs ou effets non-listés")
other_effects = models.TextField(blank=True, verbose_name="autres objectifs ou effets non listés")

def create_snapshot(
self,
Expand Down
3 changes: 2 additions & 1 deletion data/models/effect.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@

class Effect(CommonModel):
class Meta:
verbose_name = "Objectifs et effets des compléments alimentaires"
verbose_name = "Objectif et effet des compléments alimentaires"
verbose_name_plural = "Objectifs et effets des compléments alimentaires"

siccrf_name_en = models.TextField(blank=True, verbose_name="nom en anglais selon la base SICCRF")
history = HistoricalRecords(inherit=True, excluded_fields=["name", "is_obsolete"])
Expand Down
3 changes: 2 additions & 1 deletion data/models/population.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@

class Population(CommonModel):
class Meta:
verbose_name = "Population cible / à risque"
verbose_name = "Population cible"
verbose_name_plural = "Populations cibles"

min_age = models.FloatField(blank=True, null=True, default=None)
max_age = models.FloatField(blank=True, null=True, default=None)
Expand Down
File renamed without changes.
Binary file modified files/REF_ICA_FORME_GALENIQUE.csv
Binary file not shown.
Binary file added files/REF_ICA_POPULATION_ARISQUE.csv
Binary file not shown.
19 changes: 15 additions & 4 deletions frontend/src/components/DeclarationSummary/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -102,14 +102,15 @@ const unitInfo = computed(() => {
const galenicFormulationsNames = computed(() => {
if (!payload.value.galenicFormulation) return null
else if (payload.value.otherGalenicFormulation)
return "Autre (à préciser) : ".concat(payload.value.otherGalenicFormulation)
return galenicFormulations.value?.find((y) => y.id === parseInt(payload.value.galenicFormulation))?.name
})
const effectsNames = computed(() => {
const findName = (id) => effects.value?.find((y) => y.id === id)?.name
const otherEffects = payload.value.otherEffects
const allEffects = otherEffects
? payload.value.effects.map(findName).concat("Autre (à préciser) : ".concat(otherEffects))
const allEffects = payload.value.otherEffects
? payload.value.effects.map(findName).concat("Autre (à préciser) : ".concat(payload.value.otherEffects))
: payload.value.effects.map(findName)
const indexOtherEffectLabel = allEffects.indexOf("Autre (à préciser)")
Expand All @@ -125,7 +126,17 @@ const populationNames = computed(() => {
})
const conditionNames = computed(() => {
const findName = (id) => conditions.value?.find((y) => y.id === id)?.name
return payload.value.conditionsNotRecommended.map(findName).join(", ")
const allConditions = payload.value.otherConditions
? payload.value.conditionsNotRecommended
.map(findName)
.concat("Autre (à préciser) : ".concat(payload.value.otherConditions))
: payload.value.conditionsNotRecommended.map(findName)
const indexOtherConditionLabel = allConditions.indexOf("Autre (à préciser)")
if (indexOtherConditionLabel !== -1) {
allConditions.splice(indexOtherConditionLabel, 1)
}
return allConditions.join(", ")
})
const editLink = (tab) => ({ query: { tab } })
Expand Down
9 changes: 9 additions & 0 deletions frontend/src/components/fields/OtherChoiceField.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<template>
<DsfrInputGroup class="max-w-2xl mt-6 pt-8" v-if="listOfChoices && listOfChoices.indexOf(otherChoiceId) > -1">
<DsfrInput v-model="model" label-visible :label="label" :required="true" />
</DsfrInputGroup>
</template>
<script setup>
defineProps({ listOfChoices: { type: Array }, otherChoiceId: { type: Number }, label: { type: String } })
const model = defineModel()
</script>
8 changes: 4 additions & 4 deletions frontend/src/stores/root.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { defineStore } from "pinia"
import { useFetch } from "@vueuse/core"
import { ref, computed } from "vue"
import { otherFieldsAtTheEnd } from "@/utils/forms"
import { pushOtherChoiceFieldAtTheEnd } from "@/utils/forms"

export const useRootStore = defineStore("root", () => {
const loggedUser = ref(null)
Expand Down Expand Up @@ -43,15 +43,15 @@ export const useRootStore = defineStore("root", () => {
}
const fetchConditions = async () => {
const { data } = await useFetch("/api/v1/conditions/").json()
conditions.value = data.value
conditions.value = pushOtherChoiceFieldAtTheEnd(data.value)
}
const fetchEffects = async () => {
const { data } = await useFetch("/api/v1/effects/").json()
effects.value = otherFieldsAtTheEnd(data.value)
effects.value = pushOtherChoiceFieldAtTheEnd(data.value)
}
const fetchGalenicFormulations = async () => {
const { data } = await useFetch("/api/v1/galenic-formulations/").json()
galenicFormulations.value = otherFieldsAtTheEnd(data.value)
galenicFormulations.value = pushOtherChoiceFieldAtTheEnd(data.value)
}
const fetchPreparations = async () => {
const { data } = await useFetch("/api/v1/preparations/").json()
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/utils/forms.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export const getAllIndexesOfRegex = (array, regex) => {
}

// met les choix "Autre % (à préciser)" en dernier dans la liste
export const otherFieldsAtTheEnd = (choices) => {
export const pushOtherChoiceFieldAtTheEnd = (choices) => {
const otherObjsIds = getAllIndexesOfRegex(choices, /Autre.*(à préciser)/)
if (otherObjsIds) {
const otherObjs = choices.filter((obj) => otherObjsIds.includes(obj.id))
Expand Down
Loading

0 comments on commit c9ac3f5

Please sign in to comment.