Skip to content
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
17 changes: 17 additions & 0 deletions src/__tests__/components/ExportTable.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ const renderTable = (props: Partial<Parameters<typeof ExportTable>[0]> = {}) =>
compatibilitiesTables={null}
exportTypeFile="csv"
oneFile={false}
selectedTablesCount={1}
{...props}
/>
</AppConfig.Provider>
Expand Down Expand Up @@ -99,4 +100,20 @@ describe('ExportTable', () => {
renderTable({ exportTableSettings: { ...tableSetting, isChecked: false } as never })
expect(await screen.findByText('Patient')).toBeInTheDocument()
})

it('signale la sous-table patient__identifier sur la table Patient', async () => {
renderTable({ exportTable: { ...tableInfo, name: 'Patient' } })
expect(await screen.findByText(/patient__identifier sera également exportée/)).toBeInTheDocument()
})

it("masque la mention de patient__identifier en export regroupé lorsqu'une autre table est sélectionnée", async () => {
renderTable({ exportTable: { ...tableInfo, name: 'Patient' }, oneFile: true, selectedTablesCount: 2 })
await screen.findAllByText('Patient')
expect(screen.queryByText(/patient__identifier sera également exportée/)).not.toBeInTheDocument()
})

it('conserve la mention de patient__identifier en export regroupé sur la seule table Patient', async () => {
renderTable({ exportTable: { ...tableInfo, name: 'Patient' }, oneFile: true, selectedTablesCount: 1 })
expect(await screen.findByText(/patient__identifier sera également exportée/)).toBeInTheDocument()
})
})
80 changes: 80 additions & 0 deletions src/__tests__/services/serviceExportCohort.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,86 @@ describe('serviceExportCohort.postExportCohort', () => {
)
})

it('ajoute automatiquement patient__identifier quand Patient est sélectionné', async () => {
mockPost.mockResolvedValue(asAxios({ uuid: 'exp-3' }))
await postExportCohort({
// eslint-disable-next-line @typescript-eslint/no-explicit-any
cohortId: { uuid: 'cohort-3' } as any,
motivation: 'analyse',
group_tables: false,
outputFormat: 'csv',
tables: [
// eslint-disable-next-line @typescript-eslint/no-explicit-any
{ tableName: 'Patient', respectTableRelationships: true, columns: null, fhirFilter: null } as any
]
})
const payload = mockPost.mock.calls[0][1] as { export_tables: { table_name: string; cohort_result_source: string }[] }
const tableNames = payload.export_tables.map((table) => table.table_name)
expect(tableNames).toEqual(['Patient', 'patient__identifier'])
payload.export_tables.forEach((table) => {
expect(table.cohort_result_source).toBe('cohort-3')
})
})

it('ne duplique pas une sous-table liée déjà sélectionnée', async () => {
mockPost.mockResolvedValue(asAxios({ uuid: 'exp-4' }))
await postExportCohort({
// eslint-disable-next-line @typescript-eslint/no-explicit-any
cohortId: { uuid: 'cohort-4' } as any,
motivation: 'analyse',
group_tables: false,
outputFormat: 'csv',
tables: [
// eslint-disable-next-line @typescript-eslint/no-explicit-any
{ tableName: 'Patient', respectTableRelationships: true, columns: null, fhirFilter: null } as any,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
{ tableName: 'patient__identifier', respectTableRelationships: true, columns: null, fhirFilter: null } as any
]
})
const payload = mockPost.mock.calls[0][1] as { export_tables: { table_name: string }[] }
const tableNames = payload.export_tables.map((table) => table.table_name)
expect(tableNames).toEqual(['Patient', 'patient__identifier'])
expect(tableNames.filter((name) => name === 'patient__identifier')).toHaveLength(1)
})

it("n'ajoute pas patient__identifier en export regroupé quand une autre table est sélectionnée", async () => {
mockPost.mockResolvedValue(asAxios({ uuid: 'exp-5' }))
await postExportCohort({
// eslint-disable-next-line @typescript-eslint/no-explicit-any
cohortId: { uuid: 'cohort-5' } as any,
motivation: 'analyse',
group_tables: true,
outputFormat: 'csv',
tables: [
// eslint-disable-next-line @typescript-eslint/no-explicit-any
{ tableName: 'Patient', respectTableRelationships: true, columns: null, fhirFilter: null } as any,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
{ tableName: 'visit_occurrence', respectTableRelationships: true, columns: null, fhirFilter: null } as any
]
})
const payload = mockPost.mock.calls[0][1] as { export_tables: { table_name: string }[] }
const tableNames = payload.export_tables.map((table) => table.table_name)
expect(tableNames).toEqual(['Patient', 'visit_occurrence'])
})

it('ajoute patient__identifier en export regroupé quand Patient est la seule table sélectionnée', async () => {
mockPost.mockResolvedValue(asAxios({ uuid: 'exp-6' }))
await postExportCohort({
// eslint-disable-next-line @typescript-eslint/no-explicit-any
cohortId: { uuid: 'cohort-6' } as any,
motivation: 'analyse',
group_tables: true,
outputFormat: 'csv',
tables: [
// eslint-disable-next-line @typescript-eslint/no-explicit-any
{ tableName: 'Patient', respectTableRelationships: true, columns: null, fhirFilter: null } as any
]
})
const payload = mockPost.mock.calls[0][1] as { export_tables: { table_name: string }[] }
const tableNames = payload.export_tables.map((table) => table.table_name)
expect(tableNames).toEqual(['Patient', 'patient__identifier'])
})

it('omet fhir_filter quand aucun filtre n’est fourni', async () => {
mockPost.mockResolvedValue(asAxios({ uuid: 'exp-2' }))
await postExportCohort({
Expand Down
4 changes: 3 additions & 1 deletion src/pages/ExportRequest/components/ExportForm/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,7 @@ const ExportForm: React.FC = () => {
compatibilitiesTables={compatibilitiesTables}
exportTypeFile={exportTypeFile}
oneFile={oneFile}
selectedTablesCount={tablesSettings.length}
/>
))
}, [
Expand All @@ -400,7 +401,8 @@ const ExportForm: React.FC = () => {
onChangeTableSettings,
compatibilitiesTables,
exportTypeFile,
oneFile
oneFile,
tablesSettings.length
])

return (
Expand Down
9 changes: 8 additions & 1 deletion src/pages/ExportRequest/components/ExportTable/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ type ExportTableProps = {
compatibilitiesTables: string[] | null
exportTypeFile: 'xlsx' | 'csv'
oneFile: boolean
selectedTablesCount: number
}

/**
Expand Down Expand Up @@ -102,7 +103,8 @@ const ExportTable: React.FC<ExportTableProps> = ({
onChangeTableSettings,
compatibilitiesTables,
exportTypeFile,
oneFile
oneFile,
selectedTablesCount
}) => {
const dispatch = useAppDispatch()
const userId = useAppSelector((state) => state.me?.id)
Expand Down Expand Up @@ -294,6 +296,11 @@ const ExportTable: React.FC<ExportTableProps> = ({
{']'}
</Typography>
</div>
{exportTable.name === 'Patient' && (!oneFile || selectedTablesCount === 1) && (
<Typography variant="caption" fontStyle="italic" color="#888" sx={{ width: '100%', mt: '4px' }}>
La sous-table patient__identifier sera également exportée avec la table Patient.
</Typography>
)}
</Grid>

<Grid container size={4}>
Expand Down
47 changes: 37 additions & 10 deletions src/services/aphp/serviceExportCohort.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,10 @@ export const fetchExportsList = async (
}
}

const AUTO_LINKED_TABLES: Record<string, string[]> = {
Patient: ['patient__identifier']
}

export const postExportCohort = async ({
cohortId,
motivation,
Expand All @@ -151,18 +155,41 @@ export const postExportCohort = async ({
const nominative = true
const shift_date = false

const export_tables = tables.map((table: TableSetting) => ({
table_name: table.tableName,
cohort_result_source: cohortId?.uuid,
respect_table_relationships: table.respectTableRelationships,
columns: table.columns,
...(table.fhirFilter && { fhir_filter: table.fhirFilter?.uuid }),
pivot_merge_columns: table.pivotMergeColumns,
//pivot_split_columns : table.pivotSplitColumns,
pivot_merge_ids: table.pivotMergeIds
}))
// En export regroupé, une sous-table ne partage un lien hamiltonien avec sa table parente que si
// celle-ci est seule : au-delà, le dataexporter refuse la jointure sur clé primaire.
if (!group_tables || tables.length === 1) {
const existingTableNames = new Set(export_tables.map((table) => table.table_name))
tables.forEach((table: TableSetting) => {
const linkedTables = AUTO_LINKED_TABLES[table.tableName]
if (!linkedTables) return
linkedTables.forEach((linkedTableName) => {
if (existingTableNames.has(linkedTableName)) return
existingTableNames.add(linkedTableName)
export_tables.push({
table_name: linkedTableName,
cohort_result_source: cohortId?.uuid,
respect_table_relationships: table.respectTableRelationships,
columns: null,
pivot_merge_columns: undefined,
pivot_merge_ids: undefined
})
})
})
}

return await apiBackend.post<Export>('/exports/', {
motivation,
export_tables: tables.map((table: TableSetting) => ({
table_name: table.tableName,
cohort_result_source: cohortId?.uuid,
respect_table_relationships: table.respectTableRelationships,
columns: table.columns,
...(table.fhirFilter && { fhir_filter: table.fhirFilter?.uuid }),
pivot_merge_columns: table.pivotMergeColumns,
//pivot_split_columns : table.pivotSplitColumns,
pivot_merge_ids: table.pivotMergeIds
})),
export_tables,
nominative: nominative,
shift_date: shift_date,
output_format: outputFormat,
Expand Down
Loading