diff --git a/src/config.ts b/src/config.ts index 824fef3f..2fb86d89 100644 --- a/src/config.ts +++ b/src/config.ts @@ -193,10 +193,13 @@ const defaultConfig: IoDevServerConfig = { sessionTTLinMS: 60000 }, service: { - featuredItemsSize: 5, + featuredInstitutionsSize: 5, + featuredServicesSize: 5, response: { - featuredItemsResponseCode: 200, - institutionsResponseCode: 200 + featuredInstitutionsResponseCode: 200, + featuredServicesResponseCode: 200, + institutionsResponseCode: 200, + servicesByInstitutionIdResponseCode: 200 } }, allowRandomValues: true diff --git a/src/features/services/payloads/get-featured-institutions.ts b/src/features/services/payloads/get-featured-institutions.ts new file mode 100644 index 00000000..4e5a40c6 --- /dev/null +++ b/src/features/services/payloads/get-featured-institutions.ts @@ -0,0 +1,31 @@ +import * as A from "fp-ts/lib/Array"; +import { pipe } from "fp-ts/lib/function"; +import _ from "lodash"; +import { Institutions } from "../../../../generated/definitions/services/Institutions"; +import { ioDevServerConfig } from "../../../config"; +import ServicesDB from "../../../persistence/services"; +import { getInstitutions } from "../utils/institutions"; + +const featuredInstitutionsSize = + ioDevServerConfig.features.service.featuredInstitutionsSize; + +export const getFeaturedInstitutionsResponsePayload = (): Institutions => { + // take some casual institutions + const selectedInstitutions = _.sampleSize( + pipe(ServicesDB.getAllServices(), getInstitutions), + featuredInstitutionsSize + ); + + const featuredIntitutions = pipe( + selectedInstitutions, + A.map(institution => ({ + id: institution.id, + name: institution.name, + fiscal_code: institution.fiscal_code + })) + ); + + return { + institutions: featuredIntitutions + }; +}; diff --git a/src/features/services/payloads/get-featured-items.ts b/src/features/services/payloads/get-featured-services.ts similarity index 50% rename from src/features/services/payloads/get-featured-items.ts rename to src/features/services/payloads/get-featured-services.ts index 80a81aed..ca8b5cfc 100644 --- a/src/features/services/payloads/get-featured-items.ts +++ b/src/features/services/payloads/get-featured-services.ts @@ -1,35 +1,30 @@ import * as A from "fp-ts/lib/Array"; import { pipe } from "fp-ts/lib/function"; import _ from "lodash"; -import { FeaturedItem } from "../../../../generated/definitions/services/FeaturedItem"; -import { FeaturedItems } from "../../../../generated/definitions/services/FeaturedItems"; +import { FeaturedService } from "../../../../generated/definitions/services/FeaturedService"; +import { FeaturedServices } from "../../../../generated/definitions/services/FeaturedServices"; import { ioDevServerConfig } from "../../../config"; import ServicesDB from "../../../persistence/services"; -import { getInstitutionsResponsePayload } from "./get-institutions"; -const featuredItemsSize = ioDevServerConfig.features.service.featuredItemsSize; +const featuredServicesSize = + ioDevServerConfig.features.service.featuredServicesSize; -export const getFeaturedItemsResponsePayload = (): FeaturedItems => { +export const getFeaturedServicesResponsePayload = (): FeaturedServices => { // take some casual national service const selectedNationalServices = _.sampleSize( ServicesDB.getNationalServices(), - 1 + 5 ); // take some casual special service const selectedSpecialServices = _.sampleSize( ServicesDB.getSpecialServices(), - 3 - ); - // take some casual institutions - const featuredIntitutions = _.sampleSize( - Array.from(getInstitutionsResponsePayload().institutions), - 1 + 5 ); /** * Map national services to FeaturedService[] (add organization_name for layout testing purpose) */ - const featuredNationalServices: FeaturedItem[] = pipe( + const featuredNationalServices: FeaturedService[] = pipe( selectedNationalServices, A.map(service => ({ id: service.service_id, @@ -40,9 +35,9 @@ export const getFeaturedItemsResponsePayload = (): FeaturedItems => { ); /** - * Reduce special services to FeaturedService[] + * Map special services to FeaturedService[] */ - const featuredSpecialServices: FeaturedItem[] = pipe( + const featuredSpecialServices: FeaturedService[] = pipe( selectedSpecialServices, A.map(service => ({ id: service.service_id, @@ -51,17 +46,13 @@ export const getFeaturedItemsResponsePayload = (): FeaturedItems => { })) ); - // returns randomly ordered featured items - const featuredItems = _.sampleSize( - [ - ...featuredSpecialServices, - ...featuredIntitutions, - ...featuredNationalServices - ], - featuredItemsSize + // returns randomly ordered featured services + const featuredServices = _.sampleSize( + [...featuredSpecialServices, ...featuredNationalServices], + featuredServicesSize ); return { - items: featuredItems + services: featuredServices }; }; diff --git a/src/features/services/payloads/get-institutions.ts b/src/features/services/payloads/get-institutions.ts index cca9673d..20b96950 100644 --- a/src/features/services/payloads/get-institutions.ts +++ b/src/features/services/payloads/get-institutions.ts @@ -1,4 +1,5 @@ import * as A from "fp-ts/lib/Array"; +import * as O from "fp-ts/lib/Option"; import { identity, pipe } from "fp-ts/lib/function"; import _ from "lodash"; import { ServiceScopeEnum } from "../../../../generated/definitions/backend/ServiceScope"; @@ -29,7 +30,7 @@ export const getInstitutionsResponsePayload = ( offset: number = 0, scope?: ServiceScopeEnum, search?: string -): InstitutionsResource => { +): O.Option => { const filteredInstitutions = pipe( ServicesDB.getAllServices(), getInstitutions, @@ -65,10 +66,10 @@ export const getInstitutionsResponsePayload = ( const endIndex = offset + limit; const istitutionList = _.slice(filteredInstitutions, startIndex, endIndex); - return { + return O.some({ institutions: istitutionList, limit, offset, count: totalElements - }; + }); }; diff --git a/src/features/services/payloads/get-services.ts b/src/features/services/payloads/get-services.ts new file mode 100644 index 00000000..09a36c2c --- /dev/null +++ b/src/features/services/payloads/get-services.ts @@ -0,0 +1,41 @@ +import * as A from "fp-ts/lib/Array"; +import * as O from "fp-ts/lib/Option"; +import { pipe } from "fp-ts/lib/function"; +import _ from "lodash"; +import { InstitutionServicesResource } from "../../../../generated/definitions/services/InstitutionServicesResource"; +import { ServiceMinified } from "../../../../generated/definitions/services/ServiceMinified"; +import ServicesDB from "../../../persistence/services"; + +export const getServicesByInstitutionIdResponsePayload = ( + institutionId: string, + limit: number = 20, + offset: number = 0 +): O.Option => { + const filteredServices: ServiceMinified[] = pipe( + ServicesDB.getAllServices(), + A.filterMap( + ({ organization_fiscal_code, service_id, service_name, version }) => { + if (organization_fiscal_code === institutionId) { + return O.some({ + id: service_id, + name: service_name, + version + }); + } + return O.none; + } + ) + ); + + const totalElements = filteredServices.length; + const startIndex = offset; + const endIndex = offset + limit; + const servicesList = _.slice(filteredServices, startIndex, endIndex); + + return O.some({ + services: servicesList, + limit, + offset, + count: totalElements + }); +}; diff --git a/src/features/services/routers/featured.ts b/src/features/services/routers/featured.ts deleted file mode 100644 index ab841b0e..00000000 --- a/src/features/services/routers/featured.ts +++ /dev/null @@ -1,27 +0,0 @@ -import * as O from "fp-ts/lib/Option"; -import { pipe } from "fp-ts/lib/function"; -import { ioDevServerConfig } from "../../../config"; -import { addHandler } from "../../../payloads/response"; -import { getFeaturedItemsResponsePayload } from "../payloads/get-featured-items"; -import { addApiV2Prefix, serviceRouter } from "./router"; - -const serviceConfig = ioDevServerConfig.features.service; - -// Retrieve featured items -addHandler(serviceRouter, "get", addApiV2Prefix("/featured"), (_, res) => - pipe( - serviceConfig.response.featuredItemsResponseCode, - O.fromPredicate(statusCode => statusCode !== 200), - O.fold( - () => - pipe( - O.of(getFeaturedItemsResponsePayload()), - O.fold( - () => res.status(404), - featuredItems => res.status(200).json(featuredItems) - ) - ), - statusCode => res.sendStatus(statusCode) - ) - ) -); diff --git a/src/features/services/routers/index.ts b/src/features/services/routers/index.ts index a4aed809..61d93b82 100644 --- a/src/features/services/routers/index.ts +++ b/src/features/services/routers/index.ts @@ -1,4 +1,4 @@ -import "./featured"; import "./institutions"; +import "./services"; export { serviceRouter } from "./router"; diff --git a/src/features/services/routers/institutions.ts b/src/features/services/routers/institutions.ts index 544585ef..78eace4e 100644 --- a/src/features/services/routers/institutions.ts +++ b/src/features/services/routers/institutions.ts @@ -4,7 +4,9 @@ import { pipe } from "fp-ts/lib/function"; import { ServiceScope } from "../../../../generated/definitions/backend/ServiceScope"; import { ioDevServerConfig } from "../../../config"; import { addHandler } from "../../../payloads/response"; +import { getFeaturedInstitutionsResponsePayload } from "../payloads/get-featured-institutions"; import { getInstitutionsResponsePayload } from "../payloads/get-institutions"; +import { getServicesByInstitutionIdResponsePayload } from "../payloads/get-services"; import { addApiV2Prefix, serviceRouter } from "./router"; const serviceConfig = ioDevServerConfig.features.service; @@ -42,7 +44,7 @@ addHandler(serviceRouter, "get", addApiV2Prefix("/institutions"), (req, res) => pipe(req.query.search as string, O.fromNullable, O.toUndefined) ) ), - O.map(args => getInstitutionsResponsePayload(...args)), + O.chain(args => getInstitutionsResponsePayload(...args)), O.fold( () => res.status(404), instituitions => res.status(200).json(instituitions) @@ -52,3 +54,54 @@ addHandler(serviceRouter, "get", addApiV2Prefix("/institutions"), (req, res) => ) ) ); + +// Find services for institution +addHandler( + serviceRouter, + "get", + addApiV2Prefix("/institutions/:institutionId/services"), + (req, res) => + pipe( + serviceConfig.response.servicesByInstitutionIdResponseCode, + O.fromPredicate(statusCode => statusCode !== 200), + O.fold( + () => + pipe( + sequenceT(O.Monad)( + O.fromNullable(req.params.institutionId), + O.of(pipe(req.query.limit, extractQuery)), + O.of(pipe(req.query.offset, extractQuery)) + ), + O.chain(args => getServicesByInstitutionIdResponsePayload(...args)), + O.fold( + () => res.status(404), + services => res.status(200).json(services) + ) + ), + statusCode => res.sendStatus(statusCode) + ) + ) +); + +// Retrieve featured institutions +addHandler( + serviceRouter, + "get", + addApiV2Prefix("/institutions/featured"), + (_, res) => + pipe( + serviceConfig.response.featuredInstitutionsResponseCode, + O.fromPredicate(statusCode => statusCode !== 200), + O.fold( + () => + pipe( + O.of(getFeaturedInstitutionsResponsePayload()), + O.fold( + () => res.status(404), + featuredInstitutions => res.status(200).json(featuredInstitutions) + ) + ), + statusCode => res.sendStatus(statusCode) + ) + ) +); diff --git a/src/features/services/routers/services.ts b/src/features/services/routers/services.ts new file mode 100644 index 00000000..98685805 --- /dev/null +++ b/src/features/services/routers/services.ts @@ -0,0 +1,31 @@ +import * as O from "fp-ts/lib/Option"; +import { pipe } from "fp-ts/lib/function"; +import { ioDevServerConfig } from "../../../config"; +import { addHandler } from "../../../payloads/response"; +import { getFeaturedServicesResponsePayload } from "../payloads/get-featured-services"; +import { addApiV2Prefix, serviceRouter } from "./router"; + +const serviceConfig = ioDevServerConfig.features.service; + +// Retrieve featured services +addHandler( + serviceRouter, + "get", + addApiV2Prefix("/services/featured"), + (_, res) => + pipe( + serviceConfig.response.featuredServicesResponseCode, + O.fromPredicate(statusCode => statusCode !== 200), + O.fold( + () => + pipe( + O.of(getFeaturedServicesResponsePayload()), + O.fold( + () => res.status(404), + featuredServices => res.status(200).json(featuredServices) + ) + ), + statusCode => res.sendStatus(statusCode) + ) + ) +); diff --git a/src/features/services/types/configuration.ts b/src/features/services/types/configuration.ts index a06b1a1c..d33ec0a5 100644 --- a/src/features/services/types/configuration.ts +++ b/src/features/services/types/configuration.ts @@ -3,13 +3,20 @@ import * as t from "io-ts"; import { HttpResponseCode } from "../../../types/httpResponseCode"; export const ServiceConfiguration = t.type({ - // configure number of featured items - featuredItemsSize: WithinRangeNumber(0, 6), + // configure number of featured institutions + featuredInstitutionsSize: WithinRangeNumber(0, 6), + // configure number of featured services + featuredServicesSize: WithinRangeNumber(0, 6), // configure some API response error code response: t.type({ // 200 success with payload - featuredItemsResponseCode: HttpResponseCode, - institutionsResponseCode: HttpResponseCode + featuredInstitutionsResponseCode: HttpResponseCode, + // 200 success with payload + featuredServicesResponseCode: HttpResponseCode, + // 200 success with payload + institutionsResponseCode: HttpResponseCode, + // 200 success with payload + servicesByInstitutionIdResponseCode: HttpResponseCode }) });