Skip to content

Commit

Permalink
Script import Pro Connect external Ids
Browse files Browse the repository at this point in the history
  • Loading branch information
celineung committed Sep 9, 2024
1 parent e1fe83d commit df4d783
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 0 deletions.
1 change: 1 addition & 0 deletions back/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
"trigger-sending-beneficiary-assessment-emails": "ts-node src/scripts/triggerSendingBeneficiaryPdfAssessmentEmails.ts",
"trigger-suggest-edit-form-establishment-every-6-months": "ts-node src/scripts/triggerSuggestEditFormEstablishmentEvery6Months.ts",
"trigger-update-establishments-from-sirene": "ts-node src/scripts/triggerUpdateEstablishmentsFromSireneApiScript.ts",
"trigger-import-pro-connect-external-ids": "ts-node src/scripts/triggerImportProConnectExternalIds",
"typecheck": "tsc --noEmit",
"kysely-codegen": "kysely-codegen --dialect postgres",
"update-agencies-from-PE-referential": "ts-node src/scripts/updateAllPEAgenciesFromPeAgencyReferential.ts",
Expand Down
29 changes: 29 additions & 0 deletions back/src/config/pg/kysely/kyselyUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,32 @@ export type KyselyDb = Kysely<Database>;

export const falsyToNull = <T>(value: T | Falsy): T | null =>
value ? value : null;

//https://github.com/kysely-org/kysely/issues/839
//https://old.kyse.link/?p=s&i=C0yoagEodj9vv4AxE3TH
export function values<R extends Record<string, unknown>, A extends string>(
records: R[],
alias: A,
) {
// Assume there's at least one record and all records
// have the same keys.
const keys = Object.keys(records[0]);

// Transform the records into a list of lists such as
// ($1, $2, $3), ($4, $5, $6)
const values = sql.join(
records.map((r) => sql`(${sql.join(keys.map((k) => r[k]))})`),
);

// Create the alias `v(id, v1, v2)` that specifies the table alias
// AND a name for each column.
const wrappedAlias = sql.ref(alias);
const wrappedColumns = sql.join(keys.map(sql.ref));
const aliasSql = sql`${wrappedAlias}(${wrappedColumns})`;

// Finally create a single `AliasedRawBuilder` instance of the
// whole thing. Note that we need to explicitly specify
// the alias type using `.as<A>` because we are using a
// raw sql snippet as the alias.
return sql<R>`(values ${values})`.as<A>(aliasSql);
}
104 changes: 104 additions & 0 deletions back/src/scripts/triggerImportProConnectExternalIds.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import { v4 as uuid } from "uuid";
import { AppConfig } from "../config/bootstrap/appConfig";
import { createGetPgPoolFn } from "../config/bootstrap/createGateways";
import { makeKyselyDb, values } from "../config/pg/kysely/kyselyUtils";
import { createLogger } from "../utils/logger";
import { handleEndOfScriptNotification } from "./handleEndOfScriptNotification";

const logger = createLogger(__filename);

const config = AppConfig.createFromEnv();

const executeUsecase = async (): Promise<{
inCSV: number;
updated: number;
withoutProConnectIdBeforeUpdate: number;
withoutProConnectIdAfterUpdate?: {
id: string;
email: string;
external_id_inclusion_connect: string | null;
}[];
}> => {
//
// MISSING CSV Import part
//

const fake_CSV_Values: { icExternalId: string; pcExternalId: string }[] = [
{
icExternalId: "e9dce090-f45e-46ce-9c58-4fbbb3e494ba",
pcExternalId: uuid(),
},
];

const pool = createGetPgPoolFn(config)();
const db = makeKyselyDb(pool);

const getUserToUpdateQueryBuilder = db
.selectFrom("users")
.select(["id", "email", "external_id_inclusion_connect"])
.where("external_id_inclusion_connect", "is not", null)
.where("external_id_pro_connect", "is", null);

const withoutProConnectIdBeforeUpdate =
await getUserToUpdateQueryBuilder.execute();

if (fake_CSV_Values.length === 0)
return {
inCSV: fake_CSV_Values.length,
updated: 0,
withoutProConnectIdBeforeUpdate: withoutProConnectIdBeforeUpdate.length,
};

const updatedUserIds = await db
.updateTable("users")
.from(values(fake_CSV_Values, "mapping"))
.set((eb) => ({
external_id_pro_connect: eb.ref("mapping.pcExternalId"),
}))
.whereRef("mapping.icExternalId", "=", "external_id_inclusion_connect")
.returning("id")
.execute();

const userWithIcExternalAndWithoutPcExternalId =
await getUserToUpdateQueryBuilder.execute();

return {
inCSV: fake_CSV_Values.length,
withoutProConnectIdBeforeUpdate: withoutProConnectIdBeforeUpdate.length,
updated: updatedUserIds.length,
withoutProConnectIdAfterUpdate: userWithIcExternalAndWithoutPcExternalId,
};
};

/* eslint-disable @typescript-eslint/no-floating-promises */
handleEndOfScriptNotification(
"importProConnectExternalIds",
config,
executeUsecase,
({
inCSV,
updated,
withoutProConnectIdBeforeUpdate,
withoutProConnectIdAfterUpdate,
}) => {
return [
`Number of users without Pro Connect external Ids to update : ${withoutProConnectIdBeforeUpdate}`,
`Number of external Ids mapping in CSV : ${inCSV}`,
`Number of users updated with Pro Connect external Ids: ${updated}`,
...(withoutProConnectIdAfterUpdate
? [
`Number of users that still not have Pro Connect external Id details : ${withoutProConnectIdAfterUpdate.length}`,
`Details :
${[
" USER ID | EMAIL | IC_EXTERNAL_ID",
...withoutProConnectIdAfterUpdate.map(
({ id, email, external_id_inclusion_connect }) =>
`- ${id} - ${email} - ${external_id_inclusion_connect}`,
),
].join("\n ")}`,
]
: []),
].join("\n");
},
logger,
);

0 comments on commit df4d783

Please sign in to comment.