Skip to content

Commit

Permalink
feat(backend/referentiels): ajout de l'import de referentiel
Browse files Browse the repository at this point in the history
  • Loading branch information
dthib committed Oct 9, 2024
1 parent ec4be70 commit 1676aac
Show file tree
Hide file tree
Showing 19 changed files with 675 additions and 97 deletions.
4 changes: 4 additions & 0 deletions backend/src/common/models/backend-configuration.models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ export const backendConfigurationSchema = z.object({
description:
'Identifiant du dossier Google Drive pour le stockage des résultats de calcul de la trajectoire SNBC',
}),
REFERENTIEL_TE_SHEET_ID: z.string().min(1).openapi({
description:
"Identifiant de la feuille de calcul Google Sheets pour l'import du nouveau référentiel",
}),
});
export type BackendConfigurationType = z.infer<
typeof backendConfigurationSchema
Expand Down
29 changes: 29 additions & 0 deletions backend/src/common/services/zod.helper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import * as Zod from 'zod';

export const getPropertyPaths = (schema: Zod.ZodType): string[] => {
// Adjusted: Signature now uses Zod.ZodType to eliminate null& undefined check
// check if schema is nullable or optional
if (schema instanceof Zod.ZodNullable || schema instanceof Zod.ZodOptional) {
return getPropertyPaths(schema.unwrap());
}
// check if schema is an array
if (schema instanceof Zod.ZodArray) {
return getPropertyPaths(schema.element);
}
// check if schema is an object
if (schema instanceof Zod.ZodObject) {
// get key/value pairs from schema
const entries = Object.entries<Zod.ZodType>(schema.shape); // Adjusted: Uses Zod.ZodType as generic to remove instanceof check. Since .shape returns ZodRawShape which has Zod.ZodType as type for each key.
// loop through key/value pairs
return entries.flatMap(([key, value]) => {
// get nested keys
const nested = getPropertyPaths(value).map(
(subKey) => `${key}.${subKey}`
);
// return nested keys
return nested.length ? nested : key;
});
}
// return empty array
return [];
};
12 changes: 11 additions & 1 deletion backend/src/referentiels/controllers/referentiels.controller.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { createZodDto } from '@anatine/zod-nestjs';
import { Controller, Get, Logger, Param } from '@nestjs/common';
import { Controller, Get, Logger, Param, Post } from '@nestjs/common';
import { ApiResponse, ApiTags } from '@nestjs/swagger';
import { AllowPublicAccess } from '../../auth/decorators/allow-public-access.decorator';
import { TokenInfo } from '../../auth/decorators/token-info.decorators';
Expand Down Expand Up @@ -28,4 +28,14 @@ export class ReferentielsController {
): Promise<GetReferentielResponseClass> {
return this.referentielsService.getReferentiel(referentielId, true);
}

@AllowPublicAccess()
@Post(':referentiel_id/import')
@ApiResponse({ type: GetReferentielResponseClass })
async importReferentiel(
@Param('referentiel_id') referentielId: ReferentielType,
@TokenInfo() tokenInfo: SupabaseJwtPayload
): Promise<GetReferentielResponseClass> {
return this.referentielsService.importReferentiel(referentielId);
}
}
20 changes: 20 additions & 0 deletions backend/src/referentiels/models/action-definition.table.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
import { createInsertSchema, createSelectSchema } from 'drizzle-zod';
import { z } from 'zod';
import { ActionType } from './action-type.enum';
import { referentielDefinitionTable } from './referentiel-definition.table';
import { referentielList } from './referentiel.enum';

// Todo: change it reference another table instead
Expand All @@ -30,6 +31,9 @@ export const actionDefinitionTable = pgTable('action_definition', {
.notNull(),
action_id: actionIdVarchar.primaryKey().notNull(),
referentiel: referentielEnum('referentiel').notNull(),
referentiel_id: varchar('referentiel_id', { length: 30 })
.notNull()
.references(() => referentielDefinitionTable.id),
identifiant: text('identifiant').notNull(),
nom: text('nom').notNull(),
description: text('description').notNull(),
Expand Down Expand Up @@ -63,6 +67,22 @@ export const actionDefinitionMinimalWithTypeLevel =
export const createActionDefinitionSchema = createInsertSchema(
actionDefinitionTable
);
export const importActionDefinitionSchema =
createActionDefinitionSchema.partial({
action_id: true,
description: true,
nom: true,
contexte: true,
exemples: true,
ressources: true,
referentiel: true,
referentiel_id: true,
reduction_potentiel: true,
perimetre_evaluation: true,
});
export type ImportActionDefinitionType = z.infer<
typeof importActionDefinitionSchema
>;

export type ActionDefinitionAvecParentType = Pick<
ActionDefinitionType,
Expand Down
11 changes: 11 additions & 0 deletions backend/src/referentiels/models/action-type.enum.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { pgEnum } from 'drizzle-orm/pg-core';

export enum ActionType {
REFERENTIEL = 'referentiel',
AXE = 'axe',
Expand All @@ -6,3 +8,12 @@ export enum ActionType {
SOUS_ACTION = 'sous-action',
TACHE = 'tache',
}
export const orderedActionType = [
ActionType.REFERENTIEL,
ActionType.AXE,
ActionType.SOUS_AXE,
ActionType.ACTION,
ActionType.SOUS_ACTION,
ActionType.TACHE,
] as const;
export const actionTypeEnum = pgEnum('action_type', orderedActionType);
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { referentielActionDtoSchema } from './referentiel-action.dto';

export const getReferentielResponseSchema = extendApi(
z.object({
version: z.string(),
ordered_item_types: z.array(z.nativeEnum(ActionType)),
items_list: z.array(actionDefinitionMinimalWithTypeLevel).optional(),
items_tree: referentielActionDtoSchema.optional(),
Expand Down
11 changes: 11 additions & 0 deletions backend/src/referentiels/models/referentiel-changelog.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { z } from 'zod';

export const referentielChangelogSchema = z.object({
version: z.string().describe('Version du referentiel, ex: 1.0.0'),
date: z.string().describe('Date de publication de la version'),
description: z.string().describe('Description des changements de la version'),
});

export type ReferentielChangelogType = z.infer<
typeof referentielChangelogSchema
>;
31 changes: 31 additions & 0 deletions backend/src/referentiels/models/referentiel-definition.table.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { InferSelectModel, sql } from 'drizzle-orm';
import { pgTable, timestamp, varchar } from 'drizzle-orm/pg-core';
import { createInsertSchema, createSelectSchema } from 'drizzle-zod';
import { actionTypeEnum } from './action-type.enum';

export const referentielDefinitionTable = pgTable('referentiel_definition', {
id: varchar('id', { length: 30 }).primaryKey().notNull(),
nom: varchar('nom', { length: 300 }).notNull(),
version: varchar('version', { length: 16 }).notNull().default('1.0.0'),
hierarchie: actionTypeEnum('hierarchie').array().notNull(),
created_at: timestamp('created_at', { withTimezone: true, mode: 'string' })
.default(sql`CURRENT_TIMESTAMP`)
.notNull(),
modified_at: timestamp('modified_at', { withTimezone: true, mode: 'string' })
.default(sql`CURRENT_TIMESTAMP`)
.notNull(),
});

export type ReferentielDefinitionType = InferSelectModel<
typeof referentielDefinitionTable
>;
export type CreateRefentielDefinitionType = InferSelectModel<
typeof referentielDefinitionTable
>;

export const referentielDefinitionSchema = createSelectSchema(
referentielDefinitionTable
);
export const createReferentielDefinitionSchema = createInsertSchema(
referentielDefinitionTable
);
4 changes: 4 additions & 0 deletions backend/src/referentiels/models/referentiel.enum.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
export enum ReferentielType {
ECI = 'eci',
CAE = 'cae',
TE = 'te',
TE_TEST = 'te-test',
}
// WARNING: not using Object.values to use it with pgTable
export const referentielList = [
ReferentielType.CAE,
ReferentielType.ECI,
ReferentielType.TE,
ReferentielType.TE_TEST,
] as const;
2 changes: 2 additions & 0 deletions backend/src/referentiels/referentiels.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { AuthModule } from '../auth/auth.module';
import { CollectivitesModule } from '../collectivites/collectivites.module';
import { CommonModule } from '../common/common.module';
import { PersonnalisationsModule } from '../personnalisations/personnalisations.module';
import { SheetModule } from '../spreadsheets/sheet.module';
import { ReferentielsScoringController } from './controllers/referentiels-scoring.controller';
import { ReferentielsController } from './controllers/referentiels.controller';
import ReferentielsScoringService from './services/referentiels-scoring.service';
Expand All @@ -13,6 +14,7 @@ import ReferentielsService from './services/referentiels.service';
AuthModule,
CollectivitesModule,
CommonModule,
SheetModule,
PersonnalisationsModule,
],
providers: [ReferentielsService, ReferentielsScoringService],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export default class ReferentielsScoringService {
niveauAccesMinimum
);
}
await this.referentielsService.checkReferentielExists(referentielId);
await this.referentielsService.getReferentielDefinition(referentielId);

return this.collectivitesService.getCollectiviteAvecType(collectiviteId);
}
Expand Down
Loading

0 comments on commit 1676aac

Please sign in to comment.