diff --git a/front/src/modules/trainschedule/components/ImportTrainSchedule/ImportTrainScheduleTrainsList.tsx b/front/src/modules/trainschedule/components/ImportTrainSchedule/ImportTrainScheduleTrainsList.tsx index 59977dcef39..4669f89b108 100644 --- a/front/src/modules/trainschedule/components/ImportTrainSchedule/ImportTrainScheduleTrainsList.tsx +++ b/front/src/modules/trainschedule/components/ImportTrainSchedule/ImportTrainScheduleTrainsList.tsx @@ -1,18 +1,20 @@ -import { useMemo } from 'react'; +import { useCallback, useMemo } from 'react'; import { Rocket } from '@osrd-project/ui-icons'; import type { TFunction } from 'i18next'; import { keyBy } from 'lodash'; import { useTranslation } from 'react-i18next'; -import type { ImportedTrainSchedule } from 'applications/operationalStudies/types'; +import type { ImportedTrainSchedule, Step } from 'applications/operationalStudies/types'; import { osrdEditoastApi, type LightRollingStockWithLiveries, + type SearchResultItemOperationalPoint, type TrainScheduleBase, type TrainScheduleResult, } from 'common/api/osrdEditoastApi'; import { Loader } from 'common/Loaders'; +import { MAIN_OP_CH_CODES } from 'common/Map/Search/useSearchOperationalPoint'; import { ImportTrainScheduleTrainDetail } from 'modules/trainschedule/components/ImportTrainSchedule'; import rollingstockOpenData2OSRD from 'modules/trainschedule/components/ImportTrainSchedule/rollingstock_opendata2osrd.json'; import { setFailure, setSuccess } from 'reducers/main'; @@ -50,6 +52,12 @@ const ImportTrainScheduleTrainsList = ({ upsertTrainSchedules, }: ImportTrainScheduleTrainsListProps) => { const { t } = useTranslation(['operationalStudies/importTrainSchedule']); + const dispatch = useAppDispatch(); + + const [postSearch] = osrdEditoastApi.endpoints.postSearch.useMutation(); + const [postTrainSchedule] = + osrdEditoastApi.endpoints.postTimetableByIdTrainSchedule.useMutation(); + const rollingStockDict = useMemo( () => keyBy(rollingStocks, (rollingStock) => rollingStock.name), [rollingStocks] @@ -72,21 +80,50 @@ const ImportTrainScheduleTrainsList = ({ [trainsList] ); - const [postTrainSchedule] = - osrdEditoastApi.endpoints.postTimetableByIdTrainSchedule.useMutation(); - - const dispatch = useAppDispatch(); + const getStepsMainChCode = useCallback( + async (steps: Step[]) => { + const stepsQuery = ['or', ...steps.map((step) => ['=', ['uic'], Number(step.uic)])]; + const mainChCodeConstraint = [ + 'or', + ...MAIN_OP_CH_CODES.map((chCode) => ['=', ['ch'], chCode]), + ]; + + try { + const payloadSteps = { + object: 'operationalpoint', + query: ['and', stepsQuery, mainChCodeConstraint], + }; + const stepsDetails = (await postSearch({ + searchPayload: payloadSteps, + pageSize: 25, + }).unwrap()) as SearchResultItemOperationalPoint[]; + + const stepsChCodeByUIC = stepsDetails.reduce<{ [key: number]: string }>((acc, step) => { + acc[step.uic] = step.ch; + return acc; + }, {}); + + return stepsChCodeByUIC; + } catch (error) { + console.error('Failed to fetch operational points:', error); + return undefined; + } + }, + [postSearch] + ); async function generateTrainSchedules() { try { let payloads; if (trainsXmlData.length > 0) { - payloads = generateTrainSchedulesPayloads(trainsXmlData, true); + const uicToMainChCodes = await getStepsMainChCode(trainsXmlData[0].steps); + payloads = generateTrainSchedulesPayloads(trainsXmlData, uicToMainChCodes); } else if (trainsJsonData.length > 0) { payloads = trainsJsonData; } else { - payloads = generateTrainSchedulesPayloads(formattedTrainsList, false); + const uicToMainChCodes = await getStepsMainChCode(formattedTrainsList[0].steps); + payloads = generateTrainSchedulesPayloads(formattedTrainsList, uicToMainChCodes, false); } const trainSchedules = await postTrainSchedule({ id: timetableId, body: payloads }).unwrap(); diff --git a/front/src/modules/trainschedule/components/ImportTrainSchedule/generateTrainSchedulesPayloads.ts b/front/src/modules/trainschedule/components/ImportTrainSchedule/generateTrainSchedulesPayloads.ts index 425f90ea660..e0e7f8f9e27 100644 --- a/front/src/modules/trainschedule/components/ImportTrainSchedule/generateTrainSchedulesPayloads.ts +++ b/front/src/modules/trainschedule/components/ImportTrainSchedule/generateTrainSchedulesPayloads.ts @@ -8,6 +8,9 @@ import { calculateTimeDifferenceInSeconds, formatDurationAsISO8601 } from 'utils export function generateTrainSchedulesPayloads( trains: ImportedTrainSchedule[], + uicToMainChCodes?: { + [key: number]: string; + }, checkChAndUIC: boolean = true ): TrainScheduleBase[] { return trains.reduce((payloads, train) => { @@ -33,7 +36,11 @@ export function generateTrainSchedulesPayloads( return acc; // Skip invalid step } - acc.path.push({ id: stepId, uic: Number(step.uic), secondary_code: step.chCode }); + acc.path.push({ + id: stepId, + uic: Number(step.uic), + secondary_code: step.chCode || uicToMainChCodes?.[step.uic], + }); // Skip first step, handle time differences if (index !== 0) {