Skip to content

Commit

Permalink
feat: LBAC-1646 déplacement des candidatures anonymisées dans une aut…
Browse files Browse the repository at this point in the history
…re collection (#790)

* feat: création du modèle avec les champs conservés

* feat: ajout schema mongoose

* feat: suppression is_anonymized

* feat: done

* fix: import
  • Loading branch information
alanlr authored Nov 8, 2023
1 parent 12eb63b commit 02fc225
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 44 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { IAnonymizedApplication } from "shared/models/anonymizedApplications.model"

import { model, Schema } from "../../../mongodb"
import { mongoosePagination, Pagination } from "../_shared/mongoose-paginate"

export const anonymizedApplicationSchema = new Schema<IAnonymizedApplication>(
{
company_recruitment_intention: {
type: String,
default: null,
required: false,
description: "L'intention de la société vis à vis du candidat",
},
company_feedback_date: {
type: Date,
default: null,
required: false,
description: "Date d'intention/avis donnée",
},
company_siret: {
type: String,
default: null,
description: "Le siret de l'établissement",
index: true,
},
company_naf: {
type: String,
default: null,
description: "Le label naf de la société",
},
job_origin: {
type: String,
default: null,
description: "Le type de société / offre au sens source d'info La bonne alternance. Ex : lba, lbb, matcha, pejob",
},
job_id: {
type: String,
default: null,
description: "L'id externe de l'offre d'emploi",
index: true,
},
caller: {
type: String,
default: null,
description: "L'identification de la source d'émission de la candidature (pour widget et api)",
},
created_at: {
type: Date,
default: Date.now,
description: "La date création de la demande",
},
},
{
versionKey: false,
}
)

anonymizedApplicationSchema.plugin(mongoosePagination)

export default model<IAnonymizedApplication, Pagination<IAnonymizedApplication>>("applications", anonymizedApplicationSchema)
Original file line number Diff line number Diff line change
Expand Up @@ -111,11 +111,6 @@ export const applicationSchema = new Schema<IApplication>(
default: null,
description: "L'identification de la source d'émission de la candidature (pour widget et api)",
},
is_anonymized: {
type: Boolean,
default: false,
description: "Indique si la candidature a été anonymisée",
},
created_at: {
type: Date,
default: Date.now,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
import { get } from "lodash-es"

import { logger } from "../../common/logger"
import { Application } from "../../common/model/index"
import { sentryCaptureException } from "../../common/utils/sentryUtils"
import { notifyToSlack } from "../../common/utils/slackUtils"

const anonymizeApplications = async () => {
Expand All @@ -11,57 +8,47 @@ const anonymizeApplications = async () => {
const lastYear = new Date()
lastYear.setFullYear(lastYear.getFullYear() - 1)

const res = await Application.updateMany(
{ created_at: { $lte: lastYear }, is_anonymized: { $ne: true } },
await Application.aggregate([
{
$match: { created_at: { $lte: lastYear } },
},
{
$set: {
is_anonymized: true,
last_update_at: new Date(),
applicant_email: null,
applicant_first_name: null,
applicant_last_name: null,
applicant_phone: null,
applicant_attachment_name: null,
applicant_message_to_company: null,
company_feedback: null,
company_email: null,
company_name: null,
company_siret: null,
company_address: null,
job_title: null,
job_id: null,
to_applicant_message_id: null,
to_company_message_id: null,
$project: {
company_recruitment_intention: 1,
company_feedback_date: 1,
company_siret: 1,
company_naf: 1,
job_origin: 1,
job_id: 1,
caller: 1,
created_at: 1,
},
}
)
},
{
$merge: "anonymizedapplications",
},
])

return res.upserted
const res = await Application.deleteMany({ created_at: { $lte: lastYear } })

return res.deletedCount
}

export default async function () {
try {
logger.info(" -- Anonymisation des candidatures de plus de un (1) an -- ")

const anonymizedResult = await anonymizeApplications()
const nModified = anonymizedResult?.length ?? 0
const anonymizedApplicationCount = await anonymizeApplications()

logger.info(`Fin traitement ${nModified}`)
logger.info(`Fin traitement ${anonymizedApplicationCount}`)

await notifyToSlack({
subject: "ANONYMISATION CANDIDATURES",
message: `Anonymisation des candidatures de plus de un an terminée. ${nModified} candidature(s) anonymisée(s).`,
message: `Anonymisation des candidatures de plus de un an terminée. ${anonymizedApplicationCount} candidature(s) anonymisée(s).`,
error: false,
})

return {
result: "Anonymisation des candidatures terminée",
}
} catch (err: any) {
sentryCaptureException(err)
logger.error(err)
const error_msg = get(err, "meta.body") ?? err.message
await notifyToSlack({ subject: "ANONYMISATION CANDIDATURES", message: `ECHEC anonymisation des candidatures ${error_msg}`, error: true })
return { error: error_msg }
await notifyToSlack({ subject: "ANONYMISATION CANDIDATURES", message: `ECHEC anonymisation des candidatures`, error: true })
throw err
}
}
34 changes: 34 additions & 0 deletions shared/models/anonymizedApplications.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { extensions } from "../helpers/zodHelpers/zodPrimitives"
import { z } from "../helpers/zodWithOpenApi"

import { zObjectId } from "./common"

export const ZAnonymizedApplication = z
.object({
_id: zObjectId,
company_recruitment_intention: z.string().nullable().describe("L'intention de la société vis à vis du candidat"),
company_feedback_date: z.date().nullable().describe("Date d'intention/avis donnée"),
company_siret: extensions.siret.openapi({
description: "Le siret de l'entreprise. Fourni par La bonne alternance. ",
example: "00004993900000",
}),
company_naf: z.string().openapi({
description: "La valeur associée au code NAF de l'entreprise. Fournie par La bonne alternance. ",
example: "Boulangerie et boulangerie-pâtisserie",
}),
job_origin: z.string().nullable().openapi({
description: "Le type de société selon la nomenclature La bonne alternance. Fourni par La bonne alternance.",
example: "lba|lbb|matcha",
}),
job_id: z.string().nullable().openapi({
description:
"L'identifiant de l'offre La bonne alternance Recruteur pour laquelle la candidature est envoyée. Seulement si le type de la société (company_type) est \"matcha\" . La valeur est fournie par La bonne alternance. ",
example: "...59c24c059b...",
}),
caller: z.string().nullable().describe("L'identification de la source d'émission de la candidature (pour widget et api)"),
created_at: z.date().nullable().describe("La date création de la demande"),
})
.strict()
.openapi("Anonymized Application")

export type IAnonymizedApplication = z.output<typeof ZAnonymizedApplication>

0 comments on commit 02fc225

Please sign in to comment.