diff --git a/api/src/controllers/script-runner.controller.ts b/api/src/controllers/script-runner.controller.ts index 4425cafc654..6e48b3ba16c 100644 --- a/api/src/controllers/script-runner.controller.ts +++ b/api/src/controllers/script-runner.controller.ts @@ -89,6 +89,23 @@ export class ScirptRunnerController { ); } + @Put('transferListingBuildingSelectionCriteriaAssetsData') + @ApiOperation({ + summary: + 'A script that pulls listing asset data from one source into the current db', + operationId: 'transferListingBuildingSelectionCriteriaAssetsData', + }) + @ApiOkResponse({ type: SuccessDTO }) + async transferListingBuildingSelectionCriteriaAssetsData( + @Body() dataTransferDTO: AssetTransferDTO, + @Request() req: ExpressRequest, + ): Promise { + return await this.scriptRunnerService.transferListingBuildingSelectionCriteriaAssetsData( + req, + dataTransferDTO, + ); + } + @Put('transferJurisdictionPartnerUserData') @ApiOperation({ summary: diff --git a/api/src/services/script-runner.service.ts b/api/src/services/script-runner.service.ts index 13d8041af05..78630d1e1d4 100644 --- a/api/src/services/script-runner.service.ts +++ b/api/src/services/script-runner.service.ts @@ -1093,6 +1093,138 @@ export class ScriptRunnerService { return { success: true }; } + /** + * + * @param req incoming request object + * @param dataTransferDTO data transfer endpoint args. Should contain foreign db connection string + * @returns successDTO + * @description transfers building selection criteria assets for listings in the specified space into the new space + */ + async transferListingBuildingSelectionCriteriaAssetsData( + req: ExpressRequest, + dataTransferDTO: AssetTransferDTO, + prisma?: PrismaClient, + ): Promise { + // script runner standard start up + const requestingUser = mapTo(User, req['user']); + await this.markScriptAsRunStart( + `data transfer building selection criteria ${dataTransferDTO.jurisdiction}`, + requestingUser, + ); + + // connect to foreign db based on incoming connection string + const client = + prisma || + new PrismaClient({ + datasources: { + db: { + url: dataTransferDTO.connectionString, + }, + }, + }); + await client.$connect(); + + const doorwayJurisdiction = await this.prisma.jurisdictions.findFirst({ + where: { name: dataTransferDTO.jurisdiction }, + }); + + if (!doorwayJurisdiction) { + throw new Error( + `${dataTransferDTO.jurisdiction} county doesn't exist in Doorway database`, + ); + } + + // get jurisdiction + const jurisdiction: { id: string }[] = + await client.$queryRaw`SELECT id, name FROM jurisdictions WHERE name = ${dataTransferDTO.jurisdiction}`; + + if (!jurisdiction) { + throw new Error( + `${dataTransferDTO.jurisdiction} county doesn't exist in foreign database`, + ); + } + const listingTransferMap = await this.prisma.listingTransferMap.findMany({ + orderBy: { + listingId: OrderByEnum.ASC, + }, + }); + console.log(`Found ${listingTransferMap.length} listings`); + // loop over each new listing id <-> old listing id relation + for (let i = 0; i < listingTransferMap.length; i++) { + const oldAssetInfo: { + created_at: Date; + updated_at: Date; + file_id: string; + label: string; + }[] = await client.$queryRaw`SELECT + a.created_at, + a.updated_at, + a.file_id, + a.label + FROM listings l + JOIN assets a ON a.id = l.building_selection_criteria_file_id + WHERE l.id = ${listingTransferMap[i].oldId} :: UUID + AND l.building_selection_criteria_file_id IS NOT NULL`; + console.log( + `moving ${oldAssetInfo.length || 0} assets for listing: ${ + listingTransferMap[i].oldId + }:`, + ); + // loop over each listing image on the old listing + for (let j = 0; j < oldAssetInfo.length; j++) { + // pull down image from cloudinary + const image = await axios.get( + `https://res.cloudinary.com/${dataTransferDTO.cloudinaryName}/image/upload/${oldAssetInfo[j].file_id}.pdf`, + { + responseType: 'arraybuffer', + }, + ); + const newFileId = (oldAssetInfo[j].file_id as string) + .replace('housingbayarea/', '') + .replace('dev/', ''); + + // upload image to s3 + const res = await this.assetService.upload(newFileId, { + filename: null, + buffer: image.data, + fieldname: null, + originalname: `${newFileId}.pdf`, + encoding: null, + mimetype: 'application/pdf', + size: image.data.length, + destination: null, + path: null, + stream: null, + }); + + // update new listing with these assets + await this.prisma.listings.update({ + where: { + id: listingTransferMap[i].listingId, + }, + data: { + listingsBuildingSelectionCriteriaFile: { + create: { + fileId: res.url, + label: 'cloudinaryPDF', + }, + }, + }, + }); + } + } + + // disconnect from foreign db + await client.$disconnect(); + + // script runner standard spin down + await this.markScriptAsComplete( + `data transfer building selection criteria ${dataTransferDTO.jurisdiction}`, + requestingUser, + ); + return { success: true }; + } + /** * * @param amiChartImportDTO this is a string in a very specific format like: diff --git a/shared-helpers/src/types/backend-swagger.ts b/shared-helpers/src/types/backend-swagger.ts index 73f347c6d5a..27e3c9fae22 100644 --- a/shared-helpers/src/types/backend-swagger.ts +++ b/shared-helpers/src/types/backend-swagger.ts @@ -2322,6 +2322,28 @@ export class ScriptRunnerService { axios(configs, resolve, reject) }) } + /** + * A script that pulls listing asset data from one source into the current db + */ + transferListingBuildingSelectionCriteriaAssetsData( + params: { + /** requestBody */ + body?: AssetTransferDTO + } = {} as any, + options: IRequestOptions = {} + ): Promise { + return new Promise((resolve, reject) => { + let url = basePath + "/scriptRunner/transferListingBuildingSelectionCriteriaAssetsData" + + const configs: IRequestConfig = getConfigs("put", "application/json", url, options) + + let data = params.body + + configs.data = data + + axios(configs, resolve, reject) + }) + } /** * A script that pulls partner user data from one source into the current db */ @@ -6962,12 +6984,6 @@ export enum EnumUnitGroupAmiLevelMonthlyRentDeterminationType { "flatRent" = "flatRent", "percentageOfIncome" = "percentageOfIncome", } -export enum HomeTypeEnum { - "apartment" = "apartment", - "duplex" = "duplex", - "house" = "house", - "townhome" = "townhome", -} export enum EnumUnitGroupAmiLevelCreateMonthlyRentDeterminationType { "flatRent" = "flatRent", "percentageOfIncome" = "percentageOfIncome",