Skip to content

Commit

Permalink
Merge pull request #1528 from betagouv/1526
Browse files Browse the repository at this point in the history
Ajout de l'identifiant Teleicare et amélioration UX
  • Loading branch information
pletelli authored Feb 3, 2025
2 parents 267dd33 + 2fb50cd commit 4773dd8
Show file tree
Hide file tree
Showing 20 changed files with 117 additions and 61 deletions.
6 changes: 3 additions & 3 deletions api/serializers/declaration.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,8 +274,8 @@ class Meta:
model = Declaration
fields = (
"id",
"teleicare_id",
"siccrf_id",
"declared_in_teleicare",
"status",
"author",
"company",
Expand Down Expand Up @@ -558,7 +558,7 @@ class Meta:
model = Declaration
fields = (
"id",
"declared_in_teleicare",
"teleicare_id",
"article",
"status",
"author",
Expand Down Expand Up @@ -701,8 +701,8 @@ class Meta:
model = Declaration
fields = (
"id",
"teleicare_id",
"siccrf_id",
"declared_in_teleicare",
"status",
"author",
"company",
Expand Down
23 changes: 21 additions & 2 deletions data/etl/teleicare_history/extractor.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from django.db import IntegrityError, transaction

from phonenumber_field.phonenumber import PhoneNumber
from phonenumbers import NumberParseException

from data.models import (
Condition,
Expand Down Expand Up @@ -75,8 +76,11 @@ def suppress_autotime(model, fields):

def convert_phone_number(phone_number_to_parse):
if phone_number_to_parse:
phone_number = PhoneNumber.from_string(phone_number_to_parse, region="FR")
return phone_number
try:
phone_number = PhoneNumber.from_string(phone_number_to_parse, region="FR")
return phone_number
except NumberParseException:
return ""
return ""


Expand Down Expand Up @@ -193,6 +197,20 @@ def convert_str_date(value, aware=False):
return dt.date()


def create_teleicare_id(latest_ica_declaration):
if latest_ica_declaration.dcl_annee and latest_ica_declaration.dcl_mois and latest_ica_declaration.dcl_numero:
return "-".join(
[
str(getattr(latest_ica_declaration, field))
for field in [
"dcl_annee",
"dcl_mois",
"dcl_numero",
]
]
)


# Pour les déclarations TeleIcare, le status correspond au champ IcaVersionDeclaration.stattdcl_ident
DECLARATION_STATUS_MAPPING = {
1: Declaration.DeclarationStatus.ONGOING_INSTRUCTION, # 'en cours'
Expand Down Expand Up @@ -395,6 +413,7 @@ def create_declaration_from_teleicare_history():
if latest_ica_declaration.dcl_date_fin_commercialisation
else declaration_creation_date,
siccrf_id=ica_complement_alimentaire.cplalim_ident,
teleicare_id=create_teleicare_id(latest_ica_declaration),
galenic_formulation=GalenicFormulation.objects.get(
siccrf_id=ica_complement_alimentaire.frmgal_ident
),
Expand Down
23 changes: 23 additions & 0 deletions data/migrations/0120_declaration_teleicare_id_and_more.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Generated by Django 5.1.5 on 2025-01-30 15:45

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('data', '0119_merge_20250128_1101'),
]

operations = [
migrations.AddField(
model_name='declaration',
name='teleicare_id',
field=models.TextField(blank=True, editable=False, null=True, unique=True, verbose_name='identifiant Teleicare connu par les déclarants et indiqué dans les attestations'),
),
migrations.AddField(
model_name='historicaldeclaration',
name='teleicare_id',
field=models.TextField(blank=True, db_index=True, editable=False, null=True, verbose_name='identifiant Teleicare connu par les déclarants et indiqué dans les attestations'),
),
]
9 changes: 8 additions & 1 deletion data/models/declaration.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,13 @@ class Article(models.TextChoices):
unique=True,
verbose_name="cplalim_ident dans le modèle IcaComplementAlimentaire si la déclaration provient de Teleicare",
)
teleicare_id = models.TextField(
blank=True,
null=True,
editable=False,
unique=True,
verbose_name="identifiant Teleicare connu par les déclarants et indiqué dans les attestations",
)

def create_snapshot(
self,
Expand Down Expand Up @@ -396,7 +403,7 @@ def __str__(self):

@property
def declared_in_teleicare(self):
return self.siccrf_id is not None
return self.teleicare_id is not None

@property
def computed_substances_with_max_quantity_exceeded(self):
Expand Down
16 changes: 16 additions & 0 deletions frontend/src/components/DeclarationName.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<template>
<div>
<router-link :to="props.to" :text="props.text" class="mr-2"></router-link>
<HistoryBadge v-if="props.withHistoryBadge" />
</div>
</template>

<script setup>
import HistoryBadge from "@/components/History/HistoryBadge.vue"
const props = defineProps({
withHistoryBadge: { type: Boolean, default: false },
to: { type: Object },
text: { type: String },
})
</script>
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ const newArticle = ref()
onMounted(() => (newArticle.value = payload.value.article))
const payload = defineModel()
const props = defineProps({ hideArticle15Subtypes: Boolean, allowChange: Boolean })
// Aujourd'hui les subtypes (WARNING, et HIGH_RISK_POPULATION) doivent être cachés aux déclarants,
Expand Down
5 changes: 4 additions & 1 deletion frontend/src/components/DeclarationSummary/index.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<template>
<div>
<HistoryBadge v-if="!!payload.teleicareId" class="mb-2" />
<ArticleInfoRow
v-model="payload"
:hideArticle15Subtypes="!allowArticleChange"
Expand All @@ -11,6 +12,7 @@
<SummaryModificationButton class="ml-4" v-if="!readonly" @click="router.push(editLink(0))" />
</h3>
<div>
<SummaryInfoSegment v-if="!!payload.teleicareId" label="Identifiant Teleicare" :value="payload.teleicareId" />
<SummaryInfoSegment label="Nom du produit" :value="payload.name" />
<SummaryInfoSegment label="Marque" :value="payload.brand" />
<SummaryInfoSegment label="Gamme" :value="payload.gamme" />
Expand All @@ -26,7 +28,7 @@
<SummaryInfoSegment label="Durabilité minimale / DLUO (en mois)" :value="payload.minimumDuration" />
<SummaryInfoSegment label="Objectifs / effets" :value="effectsNames" />
</div>
<div v-if="!payload.declaredInTeleicare">
<div v-if="!payload.teleicareId">
<h3 class="fr-h6 !mt-8">
Composition
<SummaryModificationButton class="ml-4" v-if="!readonly" @click="router.push(editLink(1))" />
Expand Down Expand Up @@ -143,6 +145,7 @@ import { useRootStore } from "@/stores/root"
import { storeToRefs } from "pinia"
import { useRouter } from "vue-router"
import SummaryModificationButton from "./SummaryModificationButton"
import HistoryBadge from "../History/HistoryBadge.vue"
const router = useRouter()
const { units, populations, conditions, effects, galenicFormulations } = storeToRefs(useRootStore())
Expand Down
File renamed without changes.
3 changes: 3 additions & 0 deletions frontend/src/components/History/HistoryBadge.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<template>
<DsfrBadge class="fr-badge--purple-glycine" type="none" noIcon label="Historique Teleicare" ellipsis />
</template>
4 changes: 3 additions & 1 deletion frontend/src/components/SectionTitle.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
<template>
<component :is="headerTag" :class="`fr-${sizeTag} flex gap-x-2`">
<v-icon class="mt-[4px]" v-if="icon" :name="icon" />
<div>{{ title }}</div>
<div>
{{ title }}
</div>
</component>
</template>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,19 @@ import { computed } from "vue"
import { timeAgo } from "@/utils/date"
import { getStatusTagForCell } from "@/utils/components"
import CompanyTableCell from "@/components/CompanyTableCell"
import DeclarationName from "@/components/DeclarationName.vue"
import HistoryBadge from "@/components/History/HistoryBadge.vue"
const props = defineProps({ data: { type: Object, default: () => {} } })
const headers = ["ID", "Nom du produit", "Entreprise", "Auteur", "État", "Date de création", "Date de modification"]
const rows = computed(() =>
props.data?.results?.map((x) => ({
rowData: [
x.declaredInTeleicare
? {
component: "DsfrBadge",
label: "issue de Teleicare",
type: "none",
small: true,
noIcon: true,
}
: x.id,
x.teleicareId ? x.teleicareId : x.id,
{
component: "router-link",
component: DeclarationName,
withHistoryBadge: !!x.teleicareId,
text: x.name,
to: { name: "DeclarationPage", params: { id: x.id } }, // TODO Change to a more enteprisey view
},
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/views/CompanyDeclarationsPage/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ import { getPagesForPagination } from "@/utils/components"
import CompanyDeclarationsTable from "./CompanyDeclarationsTable"
import ProgressSpinner from "@/components/ProgressSpinner"
import StatusFilter from "@/components/StatusFilter.vue"
import HistoryAlert from "@/components/HistoryAlert.vue"
import HistoryAlert from "@/components/History/HistoryAlert.vue"
const route = useRoute()
const store = useRootStore()
Expand Down
16 changes: 5 additions & 11 deletions frontend/src/views/DeclarationsHomePage/DeclarationsTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { computed, ref } from "vue"
import { timeAgo } from "@/utils/date"
import { getStatusTagForCell } from "@/utils/components"
import CompanyTableCell from "@/components/CompanyTableCell"
import DeclarationName from "@/components/DeclarationName"
import { useResizeObserver, useDebounceFn } from "@vueuse/core"
const props = defineProps({ data: { type: Object, default: () => {} } })
Expand All @@ -38,17 +39,10 @@ const rows = computed(() => {
return props.data.results.map((d) => ({
rowData: [
d.declaredInTeleicare
? {
component: "DsfrBadge",
label: "issue de Teleicare",
type: "none",
small: true,
noIcon: true,
}
: d.id,
d.teleicareId ? d.teleicareId : d.id,
{
component: "router-link",
component: DeclarationName,
withHistoryBadge: !!d.teleicareId,
text: d.name,
class: "font-medium",
to: { name: "DeclarationPage", params: { id: d.id } },
Expand All @@ -61,7 +55,7 @@ const rows = computed(() => {
d.author ? `${d.author.firstName} ${d.author.lastName}` : "",
getStatusTagForCell(d.status, true),
timeAgo(d.modificationDate),
d.declaredInTeleicare
d.teleicareId
? ""
: {
component: "router-link",
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/views/DeclarationsHomePage/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ import { storeToRefs } from "pinia"
import { getPagesForPagination } from "@/utils/components"
import PaginationSizeSelect from "@/components/PaginationSizeSelect"
import StatusFilter from "@/components/StatusFilter"
import HistoryAlert from "@/components/HistoryAlert.vue"
import HistoryAlert from "@/components/History/HistoryAlert.vue"
const store = useRootStore()
const { loggedUser } = storeToRefs(store)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { storeToRefs } from "pinia"
import { articleOptionsWith15Subtypes } from "@/utils/mappings"
import CompanyTableCell from "@/components/CompanyTableCell"
import CircleIndicators from "./CircleIndicators"
import DeclarationName from "@/components/DeclarationName"
const { loggedUser } = storeToRefs(useRootStore())
Expand All @@ -33,17 +34,10 @@ const rows = computed(() =>
component: CircleIndicators,
declaration: x,
},
x.declaredInTeleicare
? {
component: "DsfrBadge",
label: "issue de Teleicare",
type: "none",
small: true,
noIcon: true,
}
: x.id,
x.teleicareId ? x.teleicareId : x.id,
{
component: "router-link",
component: DeclarationName,
withHistoryBadge: !!x.teleicareId,
text: x.name,
to: { name: "InstructionPage", params: { declarationId: x.id } },
},
Expand Down
14 changes: 7 additions & 7 deletions frontend/src/views/InstructionPage/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@
</DsfrAlert>
<DeclarationAlert
class="mb-6"
v-else-if="!canInstruct && !declaration.declaredInTeleicare"
v-else-if="!canInstruct && !declaration.teleicareId"
role="instructor"
:declaration="declaration"
:snapshots="snapshots"
/>
<DeclarationFromTeleicareAlert v-else-if="declaration.declaredInTeleicare" />
<DeclarationFromTeleicareAlert v-else-if="declaration.teleicareId" />
<div v-if="declaration">
<DeclarationSummary
:allowArticleChange="true"
:allowArticleChange="!declaration.teleicareId"
:useAccordions="true"
:showElementAuthorization="true"
:readonly="true"
Expand All @@ -62,7 +62,7 @@
:company="company"
:snapshots="snapshots"
@decision-done="onDecisionDone"
:allowArticleChange="true"
:allowArticleChange="!declaration.teleicareId"
></component>
</DsfrTabContent>
</DsfrTabs>
Expand All @@ -74,7 +74,7 @@
@forward="selectedTabIndex += 1"
:removeSaveLabel="true"
>
<template v-slot:content v-if="!declaration.declaredInTeleicare">
<template v-slot:content v-if="!declaration.teleicareId">
<h6 class="text-left">
<v-icon name="ri-pencil-fill"></v-icon>
Notes à destination de l'administration
Expand Down Expand Up @@ -122,7 +122,7 @@ import { headers } from "@/utils/data-fetching"
import DeclarationAlert from "@/components/DeclarationAlert"
import { tabTitles } from "@/utils/mappings"
import { useRouter, useRoute } from "vue-router"
import DeclarationFromTeleicareAlert from "@/components/DeclarationFromTeleicareAlert.vue"
import DeclarationFromTeleicareAlert from "@/components/History/DeclarationFromTeleicareAlert.vue"
const router = useRouter()
const route = useRoute()
Expand Down Expand Up @@ -207,7 +207,7 @@ onMounted(async () => {
// Tab management
const components = computed(() => {
const baseComponents = [IdentityTab, DeclarationSummary]
if (!declaration.value.declaredInTeleicare) baseComponents.push(HistoryTab)
if (!declaration.value.teleicareId) baseComponents.push(HistoryTab)
if (canInstruct.value) baseComponents.push(DecisionTab)
return baseComponents
})
Expand Down
Loading

0 comments on commit 4773dd8

Please sign in to comment.