Skip to content

Commit

Permalink
feat: desactivation de la tuile
Browse files Browse the repository at this point in the history
  • Loading branch information
m-maillot committed Oct 2, 2023
1 parent 0ab1d54 commit 366d7ef
Show file tree
Hide file tree
Showing 12 changed files with 232 additions and 103 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,14 @@ describe("Test enterprise endpoint", () => {
// Conventions data should be extract from elastic
conventions: Data.filter(
(doc) => doc.num === enterprise.conventions[0].idcc
).map(({ id, num, shortTitle, slug, title, url }) => ({
).map(({ id, num, shortTitle, slug, title, url, answers }) => ({
id,
num,
shortTitle,
slug,
title,
url,
hasAnswers: (answers as unknown[])?.length ?? 0 > 0,
})),
})),
};
Expand Down Expand Up @@ -236,6 +237,7 @@ describe("Test enterprise endpoint", () => {
num: 123456,
shortTitle: "Convention collective non reconnue",
id: 123456,
hasAnswers: false,
},
],
},
Expand Down Expand Up @@ -331,4 +333,100 @@ describe("Test enterprise endpoint", () => {
expect(enterprise.conventions[0].slug).not.toBeUndefined();
});
});

test("A call to retrieve not supported agreements from an enterprise", async () => {
const enterpriseApiDataResponse = {
entreprises: [
{
activitePrincipale:
"Entretien et réparation de véhicules automobiles",
conventions: [
{
idcc: 1747,
},
],
etablissements: 1,
highlightLabel: "<b><u>AUTOEXPRESS</b></u>",
label: "AUTOEXPRESS",
matching: 1,
matchingEtablissement: {
address: "1 Rue Clément Ader 08110 Carignan",
siret: "75280280100023",
},
simpleLabel: "AUTOEXPRESS",
siren: "752802801",
},
],
};
const apiEnterpriseResponse = {
json: () => enterpriseApiDataResponse,
status: 200,
};

(global as any).fetch = jest.fn(() => apiEnterpriseResponse);

const response = await request(server).get(
"/api/enterprises?q=AUTOEXPRESS"
);

expect(response.status).toEqual(200);
expect(fetch).toHaveBeenCalledTimes(1);
expect(fetch).toHaveBeenCalledWith(
`https://api.recherche-entreprises.fabrique.social.gouv.fr/api/v1/search?ranked=true&query=AUTOEXPRESS&convention=true&employer=true&open=true&matchingLimit=0`,
{ headers: { referer: "cdtn-api" } }
);

expect(response.body.entreprises[0].conventions[0].num).toEqual(1747);
expect(response.body.entreprises[0].conventions[0].hasAnswers).toEqual(
false
);
});

test("A call to retrieve supported agreements from an enterprise", async () => {
const enterpriseApiDataResponse = {
entreprises: [
{
activitePrincipale:
"Entretien et réparation de véhicules automobiles",
conventions: [
{
idcc: 843,
},
],
etablissements: 1,
highlightLabel: "<b><u>AUTOEXPRESS</b></u>",
label: "AUTOEXPRESS",
matching: 1,
matchingEtablissement: {
address: "1 Rue Clément Ader 08110 Carignan",
siret: "75280280100023",
},
simpleLabel: "AUTOEXPRESS",
siren: "752802801",
},
],
};
const apiEnterpriseResponse = {
json: () => enterpriseApiDataResponse,
status: 200,
};

(global as any).fetch = jest.fn(() => apiEnterpriseResponse);

const response = await request(server).get(
"/api/enterprises?q=AUTOEXPRESS"
);

expect(response.status).toEqual(200);
expect(fetch).toHaveBeenCalledTimes(1);
expect(fetch).toHaveBeenCalledWith(
`https://api.recherche-entreprises.fabrique.social.gouv.fr/api/v1/search?ranked=true&query=AUTOEXPRESS&convention=true&employer=true&open=true&matchingLimit=0`,
{ headers: { referer: "cdtn-api" } }
);

expect(response.body.entreprises[0].conventions[0].num).toEqual(843);
expect(response.body.entreprises[0].conventions[0].hasAnswers).toEqual(
true
);
});
});
Original file line number Diff line number Diff line change
@@ -1,18 +1,11 @@
import { NextApiRequest, NextApiResponse } from "next";
import { ENTERPRISE_API_URL } from "../../../config";
import {
DEFAULT_ERROR_500_MESSAGE,
InvalidQueryError,
NotFoundError,
} from "../../utils";
import { populateAgreements } from "./service";
import { ApiEnterpriseData, EnterpriseApiResponse } from "./types";

export type GetEnterprises = ApiEnterpriseData;
import { InvalidQueryError } from "../../utils";
import { fetchEnterprises, populateAgreements } from "./service";
import { ApiEnterpriseData } from "./types";

export class EnterprisesController {
private req: NextApiRequest;
private res: NextApiResponse;
private res: NextApiResponse<ApiEnterpriseData | ErrorResponse>;

constructor(req: NextApiRequest, res: NextApiResponse) {
this.req = req;
Expand All @@ -36,13 +29,7 @@ export class EnterprisesController {
});
}

const url = this.makeSearchUrl(query, address ?? "");

const fetchReq = await fetch(url, {
headers: { referer: "cdtn-api" },
});

const jsonResponse: EnterpriseApiResponse = await fetchReq.json();
const jsonResponse = await fetchEnterprises(query, address);

const response = await populateAgreements(jsonResponse);

Expand All @@ -51,26 +38,4 @@ export class EnterprisesController {
this.res.status(404).json({ message: "Not found" });
}
}

private makeSearchUrl = (query: string, address: string) => {
const params: { k: string; v: string }[] = [
{ k: "ranked", v: "true" },
{ k: "query", v: encodeURIComponent(query) },
{ k: "address", v: encodeURIComponent(address) },
{ k: "convention", v: "true" },
{ k: "employer", v: "true" },
{ k: "open", v: "true" },
{ k: "matchingLimit", v: "0" },
];

const flattenParams = params
.map(({ k, v }) => (k && v ? `${k}=${v}` : undefined))
.filter((qp) => qp)
.join("&");

return `${
ENTERPRISE_API_URL ??
"https://api.recherche-entreprises.fabrique.social.gouv.fr/api/v1"
}/search?${flattenParams}`;
};
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { SOURCES } from "@socialgouv/cdtn-utils";
import { Agreement, SearchResponse, SOURCES } from "@socialgouv/cdtn-utils";

type SearchAgreementsBody = {
_source: string[];
Expand All @@ -7,9 +7,24 @@ type SearchAgreementsBody = {
size: number;
};

export type AgreementResponse = Agreement & {
answers: unknown[];
};

export type SearchAgreementsResponse = SearchResponse<AgreementResponse>;

export const getAgreements = (idccList: number[]): SearchAgreementsBody => {
return {
_source: ["id", "title", "shortTitle", "num", "slug", "highlight", "url"],
_source: [
"id",
"title",
"shortTitle",
"num",
"slug",
"highlight",
"url",
"answers",
],
from: 0,
query: {
bool: {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { ENTERPRISE_API_URL } from "../../../../config";
import { Enterprise } from "../types";

export type Convention = {
idcc: number;
shortTitle: string;
id: string;
title: string;
url?: string;
};

export type EnterpriseApiResponse = {
entreprises?: (Omit<Enterprise, "conventions"> & {
conventions: Convention[];
})[];
};

export const fetchEnterprises = async (
query: string,
address: string | undefined
): Promise<EnterpriseApiResponse> => {
const params: { k: string; v: string }[] = [
{ k: "ranked", v: "true" },
{ k: "query", v: encodeURIComponent(query) },
{ k: "convention", v: "true" },
{ k: "employer", v: "true" },
{ k: "open", v: "true" },
{ k: "matchingLimit", v: "0" },
];
if (address) {
params.push({ k: "address", v: encodeURIComponent(address) });
}

const flattenParams = params
.map(({ k, v }) => (k && v ? `${k}=${v}` : undefined))
.filter((qp) => qp)
.join("&");

const url = `${
ENTERPRISE_API_URL ??
"https://api.recherche-entreprises.fabrique.social.gouv.fr/api/v1"
}/search?${flattenParams}`;

const fetchReq = await fetch(url, {
headers: { referer: "cdtn-api" },
});

const jsonResponse: EnterpriseApiResponse = await fetchReq.json();

return jsonResponse;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from "./fetchEnterprises";
export * from "./populateAgreements";
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
import { SearchResponse, Agreement } from "@socialgouv/cdtn-utils";
import { elasticDocumentsIndex, elasticsearchClient } from "../../utils";
import { getAgreements } from "./queries";
import { EnterpriseApiResponse, ApiEnterpriseData, Convention } from "./types";
import { IDCC_TO_REPLACE } from "../../config";
import { elasticDocumentsIndex, elasticsearchClient } from "../../../utils";
import {
AgreementResponse,
getAgreements,
SearchAgreementsResponse,
} from "../queries";
import { ApiEnterpriseData, EnterpriseAgreement } from "../types";
import { IDCC_TO_REPLACE } from "../../../config";
import { Convention, EnterpriseApiResponse } from "./fetchEnterprises";

const toAgreement = (convention: Convention): Agreement => ({
const toAgreement = (convention: Convention): EnterpriseAgreement => ({
id: convention.id ?? convention.idcc,
num: convention.idcc,
shortTitle: convention.shortTitle ?? "Convention collective non reconnue",
title: convention.title,
hasAnswers: false,
...(convention.url ? { url: convention.url } : {}),
});

Expand All @@ -28,13 +33,13 @@ export const populateAgreements = async (

if (idccList.length > 0) {
const body = getAgreements(idccList);
const response = await elasticsearchClient.search<
SearchResponse<Agreement>
>({ body, index: elasticDocumentsIndex });
const response = await elasticsearchClient.search<SearchAgreementsResponse>(
{ body, index: elasticDocumentsIndex }
);

if (response.body.hits.total.value > 0) {
const agreements = response.body.hits.hits.reduce(
(acc: Record<number, Agreement>, curr) => {
(acc: Record<number, AgreementResponse>, curr) => {
acc[curr._source.num] = curr._source;
return acc;
},
Expand All @@ -46,16 +51,27 @@ export const populateAgreements = async (
entreprises: enterpriseApiResponse.entreprises?.map((enterprise) => ({
...enterprise,
conventions: enterprise.conventions.map(
(convention): Agreement =>
agreements[convention.idcc] ?? toAgreement(convention)
(convention): EnterpriseAgreement => {
if (agreements[convention.idcc]) {
const { answers, ...agreement } = agreements[convention.idcc];
return {
...agreement,
hasAnswers: answers.length > 0,
};
}
return toAgreement(convention);
}
),
})),
};

if (idcc) {
const idccToAdd = IDCC_TO_REPLACE[idcc] as number[];
let conventionsToAdd: Agreement[] = idccToAdd
.map((idcc) => agreements[idcc])
let conventionsToAdd: EnterpriseAgreement[] = idccToAdd
.map((idcc) => ({
...agreements[idcc],
hasAnswers: agreements[idcc].answers.length > 0,
}))
.filter((convention) => convention !== undefined);
result.entreprises = result.entreprises?.map((enterprise) => {
const hasAlreadyIdcc = enterprise.conventions.find((convention) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export type MatchingEtablissement = {

export type Enterprise = {
activitePrincipale?: string;
conventions: Agreement[];
conventions: EnterpriseAgreement[];
etablissements: number;
highlightLabel: string;
label: string;
Expand All @@ -22,16 +22,6 @@ export type Enterprise = {
firstMatchingEtablissement?: MatchingEtablissement;
};

export type Convention = {
idcc: number;
shortTitle: string;
id: string;
title: string;
url?: string;
};

export type EnterpriseApiResponse = {
entreprises?: (Omit<Enterprise, "conventions"> & {
conventions: Convention[];
})[];
export type EnterpriseAgreement = Agreement & {
hasAnswers: boolean;
};
3 changes: 3 additions & 0 deletions packages/code-du-travail-frontend/src/api/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
type ErrorResponse = {
message: string;
};
Loading

0 comments on commit 366d7ef

Please sign in to comment.