Skip to content

Commit

Permalink
feat(api): add relation between certification and formacode sub domains
Browse files Browse the repository at this point in the history
  • Loading branch information
fbonniec committed Sep 10, 2024
1 parent e95ff34 commit 84f83af
Show file tree
Hide file tree
Showing 9 changed files with 203 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@ export const CertificationGeneralInformation = ({
{fcCertification.NOMENCLATURE_EUROPE.INTITULE}
</Info>
<Info title="Type de la certification">
{fcCertification.ABREGE.LIBELLE} ({fcCertification.ABREGE.CODE})
{fcCertification.ABREGE
? `${fcCertification.ABREGE.LIBELLE} (${fcCertification.ABREGE.CODE})`
: "Inconnue"}
</Info>
<Info title="Date fin enregistrement">
{format(fcCertification.DATE_FIN_ENREGISTREMENT, "dd/MM/yyyy")}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
import { FormacodeType } from "@prisma/client";
import { prismaClient } from "../../../prisma/client";

type Formacode = {
export type Formacode = {
id: string;
code: string;
label: string;
type: FormacodeType;
parentCode?: string;
};

export async function getFormacodes(): Promise<Formacode[]> {
const codes = await prismaClient.formacode.findMany();

const formacodes: Formacode[] = codes.map((formacode) => ({
id: formacode.id,
code: formacode.code,
label: formacode.label,
type: formacode.type,
parentCode: formacode.parentCode || undefined,
}));

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import { prismaClient } from "../../../prisma/client";
import { RNCPCertification, RNCPReferential } from "../rncp";
import { getFormacodes, Formacode } from "./getFormacodes";

export const updateCertificationWithRncpFiledsAndSubDomains = async (params: {
rncpId: string;
}) => {
const { rncpId } = params;

const certification = await prismaClient.certification.findFirst({
where: { rncpId },
});
if (!certification) {
throw new Error(
`La certification avec le code rncp ${rncpId} n'existe pas`,
);
}

const rncpCertification =
await RNCPReferential.getInstance().findOneByRncp(rncpId);
if (!rncpCertification) {
throw new Error(
`La certification avec le code rncp ${rncpId} n'existe pas dans le référentiel RNCP`,
);
}

// Update certification from based on RNCP
await prismaClient.certification.update({
where: { id: certification.id },
data: {
rncpLabel: rncpCertification.INTITULE,
rncpLevel: getLevelFromRNCPCertification(rncpCertification),
rncpTypeDiplome: rncpCertification.ABREGE?.LIBELLE,
rncpExpiresAt: new Date(rncpCertification.DATE_FIN_ENREGISTREMENT),
rncpDeliveryDeadline: rncpCertification.DATE_LIMITE_DELIVRANCE
? new Date(rncpCertification.DATE_LIMITE_DELIVRANCE)
: null,
},
});

// Link certification to sub domains
const referential = await getFormacodes();

const subDomains: Formacode[] = [];

for (const rncpFormacode of rncpCertification.FORMACODES) {
const formacode = getFormacodeByCode(rncpFormacode.CODE, referential);

if (!formacode) {
throw new Error(
`Le formacode avec le code ${rncpFormacode.CODE} n'existe pas dans le référentiel RNCP`,
);
}

const parents = getParents(formacode, referential);
const subDomain = parents.find(
(formacode) => formacode.type == "SUB_DOMAIN",
);
if (
subDomain &&
subDomains.findIndex((domain) => domain.code == subDomain.code) == -1
) {
subDomains.push(subDomain);
}
}

// Remove all links by certificationId
await prismaClient.certificationOnFormacode.deleteMany({
where: { certificationId: certification.id },
});

// Create all links
await prismaClient.certificationOnFormacode.createMany({
data: subDomains.map((subDomain) => ({
formacodeId: subDomain.id,
certificationId: certification.id,
})),
});
};

const getLevelFromRNCPCertification = (
certification: RNCPCertification,
): number => {
try {
const strLevel =
certification.NOMENCLATURE_EUROPE.INTITULE.split(" ").reverse()[0];
const level = parseInt(strLevel, 10);
return level;
} catch (error) {

Check failure on line 89 in packages/reva-api/modules/referential/features/updateCertificationWithRncpFiledsAndSubDomains.ts

View workflow job for this annotation

GitHub Actions / eslint-reva-api

'error' is defined but never used. Allowed unused args must match /^_/u
throw new Error(
`Le niveau de la certification pour le code RNCP ${certification.ID_FICHE} n'a pas pu être formatté`,
);
}
};

const getFormacodeByCode = (
code: string,
referential: Formacode[],
): Formacode | undefined => {
return referential.find((formacode) => formacode.code == code);
};

const getParent = (child: Formacode, referential: Formacode[]) => {
return referential.find((formacode) => formacode.code == child.parentCode);
};

const getParents = (
formacode: Formacode,
referential: Formacode[],
): Formacode[] => {
const parent = getParent(formacode, referential);

if (parent) {
return [...getParents(parent, referential), formacode];
}

return [formacode];
};
2 changes: 1 addition & 1 deletion packages/reva-api/modules/referential/referential.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ type FCCertification {
ID_FICHE: ID!
NUMERO_FICHE: String!
INTITULE: String!
ABREGE: FCAbrege!
ABREGE: FCAbrege
NOMENCLATURE_EUROPE: FCNomenclatureEurope!
DATE_FIN_ENREGISTREMENT: Timestamp!
DATE_LIMITE_DELIVRANCE: Timestamp
Expand Down
12 changes: 7 additions & 5 deletions packages/reva-api/modules/referential/rncp/referential.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export type RNCPCertification = {
ID_FICHE: string;
NUMERO_FICHE: string;
INTITULE: string;
ABREGE: {
ABREGE?: {
CODE: string;
LIBELLE: string;
};
Expand Down Expand Up @@ -241,10 +241,12 @@ function mapToRNCPCertification(data: any): RNCPCertification | undefined {
ID_FICHE: data.ID_FICHE,
NUMERO_FICHE: data.NUMERO_FICHE,
INTITULE: data.INTITULE,
ABREGE: {
CODE: data.ABREGE.CODE,
LIBELLE: data.ABREGE.LIBELLE,
},
ABREGE: data.ABREGE
? {
CODE: data.ABREGE.CODE,
LIBELLE: data.ABREGE.LIBELLE,
}
: undefined,
NOMENCLATURE_EUROPE: {
NIVEAU: data.NOMENCLATURE_EUROPE.NIVEAU,
INTITULE: data.NOMENCLATURE_EUROPE.INTITULE,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
-- AlterTable
ALTER TABLE "certification" ADD COLUMN "rncp_delivery_deadline" TIMESTAMPTZ(6),
ADD COLUMN "rncp_expires_at" TIMESTAMPTZ(6),
ADD COLUMN "rncp_label" VARCHAR(255),
ADD COLUMN "rncp_level" INTEGER,
ADD COLUMN "rncp_type_diplome" VARCHAR(255);
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
-- CreateTable
CREATE TABLE "certification_on_formacode" (
"id" UUID NOT NULL DEFAULT uuid_generate_v4(),
"formacode_id" UUID NOT NULL,
"certification_id" UUID NOT NULL,
"created_at" TIMESTAMPTZ(6) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMPTZ(6),

CONSTRAINT "certification_on_formacode_pkey" PRIMARY KEY ("id")
);

-- CreateIndex
CREATE UNIQUE INDEX "certification_on_formacode_formacode_id_certification_id_key" ON "certification_on_formacode"("formacode_id", "certification_id");

-- AddForeignKey
ALTER TABLE "certification_on_formacode" ADD CONSTRAINT "certification_on_formacode_formacode_id_fkey" FOREIGN KEY ("formacode_id") REFERENCES "formacode"("id") ON DELETE CASCADE ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "certification_on_formacode" ADD CONSTRAINT "certification_on_formacode_certification_id_fkey" FOREIGN KEY ("certification_id") REFERENCES "certification"("id") ON DELETE CASCADE ON UPDATE CASCADE;
23 changes: 23 additions & 0 deletions packages/reva-api/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,14 @@ model Certification {
certificationAuthorityStructureId String? @map("certification_authority_structure_id") @db.Uuid
Candidacy Candidacy[]
rncpLabel String? @map("rncp_label") @db.VarChar(255)
rncpLevel Int? @map("rncp_level")
rncpTypeDiplome String? @map("rncp_type_diplome") @db.VarChar(255)
rncpExpiresAt DateTime? @map("rncp_expires_at") @db.Timestamptz(6)
rncpDeliveryDeadline DateTime? @map("rncp_delivery_deadline") @db.Timestamptz(6)
certificationOnFormacode CertificationOnFormacode[]
@@index([typeDiplomeId])
@@map("certification")
}
Expand Down Expand Up @@ -1611,5 +1619,20 @@ model Formacode {
parent Formacode? @relation("children", fields: [parentCode], references: [code], onDelete: NoAction, onUpdate: NoAction)
children Formacode[] @relation("children")
certificationOnFormacode CertificationOnFormacode[]
@@map("formacode")
}

model CertificationOnFormacode {
id String @id @default(dbgenerated("uuid_generate_v4()")) @db.Uuid
formacode Formacode @relation(fields: [formacodeId], references: [id], onDelete: Cascade)
formacodeId String @map("formacode_id") @db.Uuid
certification Certification @relation(fields: [certificationId], references: [id], onDelete: Cascade)
certificationId String @map("certification_id") @db.Uuid
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime? @map("updated_at") @db.Timestamptz(6)
@@unique([formacodeId, certificationId])
@@map("certification_on_formacode")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { prismaClient } from "../prisma/client";

import { updateCertificationWithRncpFiledsAndSubDomains } from "../modules/referential/features/updateCertificationWithRncpFiledsAndSubDomains";

const updateAvailableCertificationsWithRncpFiledsAndSubDomains = async () => {
const certifications = await prismaClient.certification.findMany({
where: { status: "AVAILABLE" },
select: { id: true, rncpId: true },
});

for (const { rncpId } of certifications) {
await updateCertificationWithRncpFiledsAndSubDomains({ rncpId });
}
};

const main = async () => {
await updateAvailableCertificationsWithRncpFiledsAndSubDomains();
};

main();

0 comments on commit 84f83af

Please sign in to comment.