Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ajout de l'identifiant Teleicare et amélioration UX #1528

Merged
merged 25 commits into from
Feb 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
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
Loading