## 概要 [Task3570: データ変換ツール(きれいなデータ版)作成+動作確認](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/3570) - 元PBI or タスクへのリンク(内容・目的などはそちらにあるはず) - 何をどう変更したか、追加したライブラリなど - このPull Requestでの対象/対象外 - 影響範囲(他の機能にも影響があるか) ## レビューポイント - 特にレビューしてほしい箇所 - 軽微なものや自明なものは記載不要 - 修正範囲が大きい場合などに記載 - 全体的にや仕様を満たしているか等は本当に必要な時のみ記載 ## UIの変更 - Before/Afterのスクショなど - スクショ置き場 ## 動作確認状況 - ローカルで確認、develop環境で確認など ## 補足 - 相談、参考資料などがあれば
179 lines
5.6 KiB
TypeScript
179 lines
5.6 KiB
TypeScript
import {
|
||
Body,
|
||
Controller,
|
||
HttpStatus,
|
||
Post,
|
||
Req,
|
||
HttpException,
|
||
Logger,
|
||
} from "@nestjs/common";
|
||
import fs from "fs";
|
||
import { ApiOperation, ApiResponse, ApiTags } from "@nestjs/swagger";
|
||
import { Request } from "express";
|
||
import { transferRequest, transferResponse } from "./types/types";
|
||
import { TransferService } from "./transfer.service";
|
||
import { makeContext } from "../../common/log";
|
||
import { csvInputFile } from "../../common/types/types";
|
||
import { makeErrorResponse } from "src/common/errors/makeErrorResponse";
|
||
import {
|
||
COUNTRY_LIST,
|
||
MIGRATION_TYPE,
|
||
TIERS,
|
||
WORKTYPE_MAX_COUNT,
|
||
RECORDING_MODE,
|
||
LICENSE_ALLOCATED_STATUS,
|
||
USER_ROLES,
|
||
AUTO_INCREMENT_START,
|
||
} from "../../constants";
|
||
@ApiTags("transfer")
|
||
@Controller("transfer")
|
||
export class TransferController {
|
||
private readonly logger = new Logger(TransferController.name);
|
||
constructor(private readonly transferService: TransferService) {}
|
||
|
||
@Post()
|
||
@ApiResponse({
|
||
status: HttpStatus.OK,
|
||
type: transferResponse,
|
||
description: "成功時のレスポンス",
|
||
})
|
||
@ApiResponse({
|
||
status: HttpStatus.INTERNAL_SERVER_ERROR,
|
||
description: "想定外のサーバーエラー",
|
||
})
|
||
@ApiOperation({ operationId: "dataRegist" })
|
||
async dataRegist(
|
||
@Body() body: transferRequest,
|
||
@Req() req: Request
|
||
): Promise<transferResponse> {
|
||
const context = makeContext("iko", "transfer");
|
||
|
||
const inputFilePath = body.inputFilePath;
|
||
|
||
this.logger.log(
|
||
`[IN] [${context.getTrackingId()}] ${
|
||
this.dataRegist.name
|
||
} | params: { inputFilePath: ${inputFilePath}};`
|
||
);
|
||
try {
|
||
// 読み込みファイルのフルパス
|
||
const csvFileFullPath = inputFilePath + ".csv";
|
||
|
||
// ファイル存在チェックと読み込み
|
||
if (!fs.existsSync(csvFileFullPath)) {
|
||
this.logger.error(`file not exists from ${inputFilePath}`);
|
||
throw new Error(`file not exists from ${inputFilePath}`);
|
||
}
|
||
|
||
// CSVファイルを全行読み込む
|
||
const inputFile = fs.readFileSync(csvFileFullPath, "utf-8");
|
||
|
||
// レコードごとに分割
|
||
const csvInputFileLines = inputFile.split("\n");
|
||
|
||
// ヘッダー行を削除
|
||
csvInputFileLines.shift();
|
||
|
||
// 項目ごとに切り分ける
|
||
let csvInputFile: csvInputFile[] = [];
|
||
csvInputFileLines.forEach((line) => {
|
||
const data = line.split(",");
|
||
// ダブルクォーテーションは削除
|
||
data.forEach((value, index) => {
|
||
data[index] = value.replace(/"/g, "");
|
||
});
|
||
csvInputFile.push({
|
||
type: data[0],
|
||
account_id: data[1],
|
||
parent_id: data[2],
|
||
email: data[3],
|
||
company_name: data[4],
|
||
first_name: data[5],
|
||
last_name: data[6],
|
||
country: data[7],
|
||
state: data[8],
|
||
start_date: new Date(data[9]),
|
||
expired_date: new Date(data[10]),
|
||
user_email: data[11],
|
||
author_id: data[12],
|
||
recording_mode: data[13],
|
||
wt1: data[14],
|
||
wt2: data[15],
|
||
wt3: data[16],
|
||
wt4: data[17],
|
||
wt5: data[18],
|
||
wt6: data[19],
|
||
wt7: data[20],
|
||
wt8: data[21],
|
||
wt9: data[22],
|
||
wt10: data[23],
|
||
wt11: data[24],
|
||
wt12: data[25],
|
||
wt13: data[26],
|
||
wt14: data[27],
|
||
wt15: data[28],
|
||
wt16: data[29],
|
||
wt17: data[30],
|
||
wt18: data[31],
|
||
wt19: data[32],
|
||
wt20: data[33],
|
||
});
|
||
});
|
||
|
||
// 各データのバリデーションチェック
|
||
await this.transferService.validateInputData(context, csvInputFile);
|
||
|
||
// account_idを通番に変換し、変換前account_id: 変換後accountId配列を作成する。
|
||
const accountIdList = csvInputFile.map((line) => line.account_id);
|
||
const accountIdListSet = new Set(accountIdList);
|
||
const accountIdListArray = Array.from(accountIdListSet);
|
||
const accountIdMap = new Map<string, number>();
|
||
accountIdListArray.forEach((accountId, index) => {
|
||
accountIdMap.set(accountId, index + AUTO_INCREMENT_START);
|
||
});
|
||
// CSVファイルの変換
|
||
const transferResponse = await this.transferService.registInputData(
|
||
context,
|
||
csvInputFile,
|
||
accountIdMap
|
||
);
|
||
|
||
// countryを除いた階層の再配置
|
||
const accountsOutputFileStep1Lines =
|
||
transferResponse.accountsOutputFileStep1Lines;
|
||
const accountsOutputFile = await this.transferService.relocateHierarchy(
|
||
context,
|
||
accountsOutputFileStep1Lines
|
||
);
|
||
// メールアドレスの重複を削除
|
||
// デモライセンスの削除
|
||
// いったんこのままコミットしてテストを実施する
|
||
|
||
// transferResponseを4つのJSONファイルの出力する(出力先はinputと同じにする)
|
||
const outputFilePath = body.inputFilePath;
|
||
const usersOutputFile = transferResponse.usersOutputFileLines;
|
||
const licensesOutputFile = transferResponse.licensesOutputFileLines;
|
||
const worktypesOutputFile = transferResponse.worktypesOutputFileLines;
|
||
this.transferService.outputJsonFile(
|
||
context,
|
||
outputFilePath,
|
||
accountsOutputFile,
|
||
usersOutputFile,
|
||
licensesOutputFile,
|
||
worktypesOutputFile
|
||
);
|
||
return {};
|
||
} catch (e) {
|
||
this.logger.error(`[${context.getTrackingId()}] error=${e}`);
|
||
throw new HttpException(
|
||
makeErrorResponse("E009999"),
|
||
HttpStatus.INTERNAL_SERVER_ERROR
|
||
);
|
||
} finally {
|
||
this.logger.log(
|
||
`[OUT] [${context.getTrackingId()}] ${this.dataRegist.name}`
|
||
);
|
||
}
|
||
}
|
||
}
|