import APIUrls, {
APIV2RequestDatetimeFormat,
} from '@/config/simpliciti-apis.js'
import moment from 'moment'
import { getNestedValue } from '@/utils/object.js'
import api from '@/api'
import FixturesService from '@/api/fixtures.js'
import { getAPIV3Pooling } from '@/api'
const R = require('ramda')
/**
*
* Used by:
* Location - Main search -> History by Circuit
* Location - Main search -> History by Vehicle/Driver -> Circuit Tab
*
* @param {Number} circuitId [OPTIONAL]
* @param {String} date Circuit execution start date
* @returns Normalized circuit execution detail item
*/
export async function getCircuitExecutionDetails({
circuitId,
date,
...params
} = {}) {
let m = moment(date)
date = m.format('YYYY-MM-DD')
let from = m.format('HH:mm')
let to = m.hour(23).minute(59).second(59).format('HH:mm')
circuitId = circuitId ? `&circuit_id=${circuitId}` : ''
let apiResponse = (
await api.v2.post(
`${
APIUrls.APIV2_HISTORIQUE_BY_CIRCUIT_DATES
}?dates=${date}&heure_debut=${encodeURI(from)}&heure_fin=${encodeURI(
to
)}&infos_gps=false&linestring=false&troncons=true${circuitId}`
)
).data
let rawItem = getFirstProperty(getFirstProperty(apiResponse))
let historyItem = getFirstProperty(rawItem.historique)
//As API doesn't let us filter by execution, sometimes it could bring two executions and we need to filter (i.g location/history by circuit: details)
if (params.circuitExecutionId) {
Object.keys(rawItem.historique).forEach((circuitExecutionId) => {
if (
circuitExecutionId.toString() == params.circuitExecutionId.toString()
) {
historyItem = rawItem.historique[circuitExecutionId]
}
})
}
let result = normalizeCircuitExecutionDetailsItem({
...rawItem,
...historyItem,
})
result.troncons = (result.troncons || []).sort((a, b) =>
parseInt(a.id) > parseInt(b.id) ? 1 : -1
)
return result
}
/**
*
* Used by:
* Location - Main search -> Real-time by Vehicle/Driver/Circuit
*
* Get last executed circuit infos from fixtures or API.
* @warn APIV2 response: Attribute "historique" will always contain one item
* @todo Remove fixtures feature without braking unit test
* @param {Object} {vehicleId}
* @returns Normalized circuit execution detail item
*/
export async function getLastCircuitExecutionDetails({ vehicleId }) {
if (!vehicleId) {
return {}
}
let extraParams = '&troncons=true'
let apiResponse =
(await FixturesService.loadFixtures(
`${APIUrls.APIV2_HISTORIQUE_DERNIER_CIRCUIT.substring(1)}/${vehicleId}`
)) ||
(
await api.v2.post(
`${APIUrls.APIV2_HISTORIQUE_DERNIER_CIRCUIT}?vehicule_id=${vehicleId}&execution_en_cours=true${extraParams}`
)
).data
if (apiResponse.length !== undefined && apiResponse.length === 0) {
apiResponse = null
}
if (apiResponse) {
let rawItem = getFirstProperty(getFirstProperty(apiResponse))
return normalizeCircuitExecutionDetailsItem({
...rawItem,
...getFirstProperty(rawItem.historique),
})
} else {
return {}
}
}
/**
* Used by:
* Location - Main search -> Real-time by Vehicle/Driver/Circuit
* @param {*} object
* @returns
*/
function getFirstProperty(object) {
return (
(Object.keys(object || {}).length > 0 && object[Object.keys(object)[0]]) ||
{}
)
}
/**
* Transform/Presenter function for circuit execution details item
*
* @param {*} item Details item from APIV2 Historique by_circuit_dates or APIV2 dernier_circuit
* @returns
*/
function normalizeCircuitExecutionDetailsItem(item) {
item = {
//raw response
...item,
//transform fields (use these when possible)
circuit_nom_court: item.circuit_nom_court,
circuit_nom_long: item.circuit_nom_long,
circuit_categorie: item.circuit_categorie,
circuit_id: item.circuit_id,
dateFrom: getNestedValue(item, ['dh_exec_circuit_debut']),
dateTo: getNestedValue(item, ['dh_exec_circuit_fin']),
}
return R.omit(['historique'], item)
}
/**
* @deprecated: Last "last circuit" API already brings troncons attribute if &trocons=1 is supplied (see getLastCircuitExecutionDetails)
* Circuit execution steps/troncons
*
* @param {Number} vehicleId
* @param {Number} circuitId
* @param {String} fromDate Circuit execution start date
* @param {String} toDate Circuit execution end date
* @returns
*/
export async function getCircuitExecutionSteps({
vehicleId,
circuitId,
fromDate,
toDate,
}) {
console.debug('getCircuitExecutionSteps', {
fromDate,
toDate,
})
let fromDateStr = encodeURI(
moment(fromDate, APIV2RequestDatetimeFormat).format(
APIV2RequestDatetimeFormat
)
)
toDate = encodeURI(
moment(toDate, APIV2RequestDatetimeFormat).format(
APIV2RequestDatetimeFormat
)
)
let data = (
await api.v2.post(
`${APIUrls.APIV2_HISTORIQUE_CIRCUIT_TRONCONS}?dateheure_debut=${fromDateStr}&dateheure_fin=${toDate}&vehicule_id=${vehicleId}&circuit_id=${circuitId}`
)
).data
return data.length >= 1 ? data[0] : {}
}
export async function fetchCircuitCategories(transform = null) {
return await getAPIV3Pooling({
uri: `${APIUrls.APIV3_ROUND_CATEGORIES}?page=1&itemsPerPage=500&order[label]=asc`,
transform: transform,
})
}
/**
* @warn Steven: transform/normalization should be not extracted from circuit-service. If you need two differents normalization, instead, split into two different functions: fetchCircuitsV3/fetchCircuitsV2
* @todo SearchModule: Move the normalization from search_module into this function (default normalization)
* @param {*} transform
* @returns
*/
export async function fetchCircuits(transform = null) {
return await getAPIV3Pooling({
uri: `${APIUrls.APIV3_ROUNDS}?page=1&itemsPerPage=500&order[shortName]=asc`,
transform: transform,
})
}
export function normalizeRoundCategoryToV2(c) {
const parentId = getNestedValue(c, 'parentId')
let result = {
id: getNestedValue(c, 'id'),
libelle: getNestedValue(c, 'label'),
parent_id: parentId == '' ? null : parentId,
}
return result
}
export function normalizeRoundToV2(c, categoryList) {
let categoryId = null
if (!c?._links?.category?.href) {
//tries to set "sans category" category
categoryId = (
categoryList.find(
(ctg) => ctg.libelle.toLowerCase().indexOf('sans ') !== -1
) || {}
).id
} else {
categoryId = getNestedValue(c, '_links.category.href').match(/\d+/)[0]
}
const category = categoryList.find((c) => c.id == categoryId)
let result = {
id: getNestedValue(c, 'id'),
circuit_id: getNestedValue(c, 'id'),
nom_court: getNestedValue(c, 'shortName'),
category_id: categoryId,
categorie_nom: category.libelle,
}
if (category?.parent_id) {
const parentCategory =
categoryList.find((c) => c.id === category.parent_id) || null
result = {
...result,
parentCategoryName: parentCategory ? parentCategory.libelle : '',
}
}
return result
}
export default {
getLastCircuitExecutionDetails,
getCircuitExecutionDetails,
getCircuitExecutionSteps,
fetchCircuitCategories,
fetchCircuits,
normalizeRoundCategoryToV2,
normalizeRoundToV2,
}
Source