Merged PR 796: [3回目実行][フルデータ]develop環境での移行実施後の修正作業
## 概要 [Task3802: [3回目実行][フルデータ]develop環境での移行実施後の修正作業](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/3802) - 元PBI or タスクへのリンク(内容・目的などはそちらにあるはず) - 何をどう変更したか、追加したライブラリなど - このPull Requestでの対象/対象外 - 影響範囲(他の機能にも影響があるか) ## レビューポイント - 特にレビューしてほしい箇所 - 軽微なものや自明なものは記載不要 - 修正範囲が大きい場合などに記載 - 全体的にや仕様を満たしているか等は本当に必要な時のみ記載 ## UIの変更 - Before/Afterのスクショなど - スクショ置き場 ## 動作確認状況 - ローカルで確認、develop環境で確認など ## 補足 - 相談、参考資料などがあれば
This commit is contained in:
parent
cad3a99f70
commit
88ce6a2c9e
@ -73,7 +73,8 @@ export class TransferController {
|
|||||||
const matchList = line.match(regExp);
|
const matchList = line.match(regExp);
|
||||||
if (matchList) {
|
if (matchList) {
|
||||||
matchList.forEach((match) => {
|
matchList.forEach((match) => {
|
||||||
const replaced = match.replace(/,/g, " ");
|
// カンマを\に変換
|
||||||
|
const replaced = match.replace(/,/g, "\\");
|
||||||
line = line.replace(match, replaced);
|
line = line.replace(match, replaced);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -95,7 +96,12 @@ export class TransferController {
|
|||||||
HttpStatus.BAD_REQUEST
|
HttpStatus.BAD_REQUEST
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
// data[1]がundefinedの場合、配列には格納しない
|
||||||
|
if (data[1] !== undefined) {
|
||||||
|
// バックスラッシュをカンマに戻す
|
||||||
|
data.forEach((value, index) => {
|
||||||
|
data[index] = value.replace(/\\/g, ",");
|
||||||
|
});
|
||||||
csvInputFile.push({
|
csvInputFile.push({
|
||||||
type: data[0],
|
type: data[0],
|
||||||
account_id: data[1],
|
account_id: data[1],
|
||||||
@ -132,12 +138,8 @@ export class TransferController {
|
|||||||
wt19: data[32],
|
wt19: data[32],
|
||||||
wt20: data[33],
|
wt20: data[33],
|
||||||
});
|
});
|
||||||
});
|
|
||||||
// 最後の行がundefinedの場合はその行を削除
|
|
||||||
if (csvInputFile[csvInputFile.length - 1].account_id === undefined) {
|
|
||||||
csvInputFile.pop();
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
// 各データのバリデーションチェック
|
// 各データのバリデーションチェック
|
||||||
await this.transferService.validateInputData(context, csvInputFile);
|
await this.transferService.validateInputData(context, csvInputFile);
|
||||||
|
|
||||||
@ -155,8 +157,8 @@ export class TransferController {
|
|||||||
accountIdMap.forEach((value, key) => {
|
accountIdMap.forEach((value, key) => {
|
||||||
const accountsMappingFile = new AccountsMappingFile();
|
const accountsMappingFile = new AccountsMappingFile();
|
||||||
accountsMappingFile.accountIdNumber = value;
|
accountsMappingFile.accountIdNumber = value;
|
||||||
accountsMappingFile.accountIdText = key
|
accountsMappingFile.accountIdText = key;
|
||||||
accountsMappingFiles.push(accountsMappingFile)
|
accountsMappingFiles.push(accountsMappingFile);
|
||||||
});
|
});
|
||||||
|
|
||||||
fs.writeFileSync(
|
fs.writeFileSync(
|
||||||
@ -188,6 +190,13 @@ export class TransferController {
|
|||||||
LicensesFile
|
LicensesFile
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// AuthorIDが重複している場合通番を付与する
|
||||||
|
const transferDuplicateAuthorResultUsers =
|
||||||
|
await this.transferService.transferDuplicateAuthor(
|
||||||
|
context,
|
||||||
|
resultDuplicateEmail.usersFileLines
|
||||||
|
);
|
||||||
|
|
||||||
// transferResponseCsvを4つのJSONファイルの出力する(出力先はinputと同じにする)
|
// transferResponseCsvを4つのJSONファイルの出力する(出力先はinputと同じにする)
|
||||||
const outputFilePath = body.inputFilePath;
|
const outputFilePath = body.inputFilePath;
|
||||||
const WorktypesFile = transferResponseCsv.worktypesFileLines;
|
const WorktypesFile = transferResponseCsv.worktypesFileLines;
|
||||||
@ -195,7 +204,7 @@ export class TransferController {
|
|||||||
context,
|
context,
|
||||||
outputFilePath,
|
outputFilePath,
|
||||||
resultDuplicateEmail.accountsFileLines,
|
resultDuplicateEmail.accountsFileLines,
|
||||||
resultDuplicateEmail.usersFileLines,
|
transferDuplicateAuthorResultUsers,
|
||||||
resultDuplicateEmail.licensesFileLines,
|
resultDuplicateEmail.licensesFileLines,
|
||||||
WorktypesFile
|
WorktypesFile
|
||||||
);
|
);
|
||||||
|
|||||||
@ -54,6 +54,12 @@ export class TransferService {
|
|||||||
let userIdIndex = 0;
|
let userIdIndex = 0;
|
||||||
// authorIdとuserIdの対応関係を保持するMapを定義
|
// authorIdとuserIdの対応関係を保持するMapを定義
|
||||||
const authorIdToUserIdMap: Map<string, number> = new Map();
|
const authorIdToUserIdMap: Map<string, number> = new Map();
|
||||||
|
|
||||||
|
// countryのリストを生成
|
||||||
|
const countryAccounts = csvInputFile.filter(
|
||||||
|
(item) => item.type === "Country"
|
||||||
|
);
|
||||||
|
|
||||||
// csvInputFileを一行読み込みする
|
// csvInputFileを一行読み込みする
|
||||||
csvInputFile.forEach((line) => {
|
csvInputFile.forEach((line) => {
|
||||||
// typeが"USER"以外の場合、アカウントデータの作成を行う
|
// typeが"USER"以外の場合、アカウントデータの作成を行う
|
||||||
@ -105,8 +111,13 @@ export class TransferService {
|
|||||||
authorId: null,
|
authorId: null,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// typeが"USER"の場合
|
// typeが"USER"の場合、かつcountryのアカウントIDに所属していない場合
|
||||||
if (line.type == MIGRATION_TYPE.USER) {
|
if (
|
||||||
|
line.type == MIGRATION_TYPE.USER &&
|
||||||
|
!countryAccounts.some(
|
||||||
|
(countryAccount) => countryAccount.account_id === line.account_id
|
||||||
|
)
|
||||||
|
) {
|
||||||
// line.author_idが存在する場合のみユーザーデータを作成する
|
// line.author_idが存在する場合のみユーザーデータを作成する
|
||||||
if (line.author_id) {
|
if (line.author_id) {
|
||||||
// userIdIndexをインクリメントする
|
// userIdIndexをインクリメントする
|
||||||
@ -229,46 +240,38 @@ export class TransferService {
|
|||||||
const relocatedAccounts: AccountsFile[] = [];
|
const relocatedAccounts: AccountsFile[] = [];
|
||||||
const dealerRecords: Map<number, number> = new Map();
|
const dealerRecords: Map<number, number> = new Map();
|
||||||
|
|
||||||
// accountsFileTypeをループ
|
const countryAccounts = accountsFileType.filter(
|
||||||
accountsFileType.forEach((account) => {
|
(item) => item.type === MIGRATION_TYPE.COUNTRY
|
||||||
// Distributorの場合はdealerを検索し、COUNTRYかチェックする
|
|
||||||
if (account.type === MIGRATION_TYPE.DISTRIBUTOR) {
|
|
||||||
const distributorParent = accountsFileType.find(
|
|
||||||
(a) => a.accountId === account.dealerAccountId
|
|
||||||
);
|
);
|
||||||
if (distributorParent.type === MIGRATION_TYPE.COUNTRY) {
|
|
||||||
dealerRecords.set(
|
|
||||||
account.accountId,
|
|
||||||
distributorParent.dealerAccountId // Countryの親、BCのIDを設定
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
dealerRecords.set(account.accountId, account.dealerAccountId);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// AccountsFileTypeのループを行い、階層情報の置換と新たな配列へのpushを行う
|
const notCountryAccounts = accountsFileType.filter(
|
||||||
accountsFileType.forEach((account) => {
|
(item) => item.type !== MIGRATION_TYPE.COUNTRY
|
||||||
// Countryのレコードは除外する
|
);
|
||||||
if (account.type !== MIGRATION_TYPE.COUNTRY) {
|
|
||||||
const dealerAccountId =
|
notCountryAccounts.forEach((notCountryAccount) => {
|
||||||
dealerRecords.get(account.accountId) ?? account.dealerAccountId;
|
let assignDealerAccountId = notCountryAccount.dealerAccountId;
|
||||||
const type = this.getAccountType(account.type);
|
// 親アカウントIDがcountryの場合、countryの親アカウントIDを設定する
|
||||||
|
for (const countryAccount of countryAccounts) {
|
||||||
|
if (countryAccount.accountId === notCountryAccount.dealerAccountId) {
|
||||||
|
assignDealerAccountId = countryAccount.dealerAccountId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const assignType = this.getAccountType(notCountryAccount.type);
|
||||||
|
|
||||||
const newAccount: AccountsFile = {
|
const newAccount: AccountsFile = {
|
||||||
accountId: account.accountId,
|
accountId: notCountryAccount.accountId,
|
||||||
type: type,
|
type: assignType,
|
||||||
companyName: account.companyName,
|
companyName: notCountryAccount.companyName,
|
||||||
country: account.country,
|
country: notCountryAccount.country,
|
||||||
dealerAccountId: dealerAccountId,
|
dealerAccountId: assignDealerAccountId,
|
||||||
adminName: account.adminName,
|
adminName: notCountryAccount.adminName,
|
||||||
adminMail: account.adminMail,
|
adminMail: notCountryAccount.adminMail,
|
||||||
userId: account.userId,
|
userId: notCountryAccount.userId,
|
||||||
role: account.role,
|
role: notCountryAccount.role,
|
||||||
authorId: account.authorId,
|
authorId: notCountryAccount.authorId,
|
||||||
};
|
};
|
||||||
|
|
||||||
relocatedAccounts.push(newAccount);
|
relocatedAccounts.push(newAccount);
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return relocatedAccounts;
|
return relocatedAccounts;
|
||||||
@ -364,6 +367,8 @@ export class TransferService {
|
|||||||
);
|
);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// エラー配列を定義
|
||||||
|
let errorArray: string[] = [];
|
||||||
// アカウントに対するworktypeのMap配列を作成する
|
// アカウントに対するworktypeのMap配列を作成する
|
||||||
const accountWorktypeMap = new Map<string, string[]>();
|
const accountWorktypeMap = new Map<string, string[]>();
|
||||||
// csvInputFileのバリデーションチェックを行う
|
// csvInputFileのバリデーションチェックを行う
|
||||||
@ -383,6 +388,13 @@ export class TransferService {
|
|||||||
HttpStatus.BAD_REQUEST
|
HttpStatus.BAD_REQUEST
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
// typeがUSER以外の場合で、countryがnullの場合エラー配列に格納する
|
||||||
|
if (line.type !== MIGRATION_TYPE.USER) {
|
||||||
|
if (!line.country) {
|
||||||
|
// countryがnullの場合エラー配列に格納する
|
||||||
|
errorArray.push(`country is null. index=${index}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
// countryのバリデーションチェック
|
// countryのバリデーションチェック
|
||||||
if (line.country) {
|
if (line.country) {
|
||||||
if (!COUNTRY_LIST.find((country) => country.label === line.country)) {
|
if (!COUNTRY_LIST.find((country) => country.label === line.country)) {
|
||||||
@ -451,6 +463,15 @@ export class TransferService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
// エラー配列に値が存在する場合はエラーファイルを出力する
|
||||||
|
if (errorArray.length > 0) {
|
||||||
|
const errorFileJson = JSON.stringify(errorArray);
|
||||||
|
fs.writeFileSync(`error.json`, errorFileJson);
|
||||||
|
throw new HttpException(
|
||||||
|
`errorArray is invalid. errorArray=${errorArray}`,
|
||||||
|
HttpStatus.BAD_REQUEST
|
||||||
|
);
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.logger.error(`[${context.getTrackingId()}] error=${e}`);
|
this.logger.error(`[${context.getTrackingId()}] error=${e}`);
|
||||||
throw new HttpException(
|
throw new HttpException(
|
||||||
@ -603,4 +624,67 @@ export class TransferService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* transferDuplicateAuthor
|
||||||
|
* @param usersFileLines: UsersFile[]
|
||||||
|
* @returns UsersFile[]
|
||||||
|
*/
|
||||||
|
async transferDuplicateAuthor(
|
||||||
|
context: Context,
|
||||||
|
usersFileLines: UsersFile[]
|
||||||
|
): Promise<UsersFile[]> {
|
||||||
|
// パラメータ内容が長大なのでログには出さない
|
||||||
|
this.logger.log(
|
||||||
|
`[IN] [${context.getTrackingId()}] ${this.transferDuplicateAuthor.name}`
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const newUsersFileLines: UsersFile[] = [];
|
||||||
|
|
||||||
|
let processingAccountId: number = 0; //処理中のアカウントID
|
||||||
|
let duplicateSequence: number = 2;
|
||||||
|
let authorIdList: String[] = [];
|
||||||
|
for (const user of usersFileLines) {
|
||||||
|
if (user.accountId !== processingAccountId) {
|
||||||
|
//アカウントIDが別になった場合、通番を初期化する
|
||||||
|
duplicateSequence = 2;
|
||||||
|
processingAccountId = user.accountId;
|
||||||
|
authorIdList = [];
|
||||||
|
}
|
||||||
|
let assignAuthorId = user.authorId;
|
||||||
|
if (authorIdList.includes(user.authorId)) {
|
||||||
|
// 同じauthorIdがいる場合、自分のauthorIdに連番を付与する
|
||||||
|
assignAuthorId = assignAuthorId + duplicateSequence;
|
||||||
|
duplicateSequence = duplicateSequence + 1;
|
||||||
|
}
|
||||||
|
authorIdList.push(user.authorId);
|
||||||
|
|
||||||
|
// 新しいAuthorIdのユーザに詰め替え
|
||||||
|
const newUser: UsersFile = {
|
||||||
|
accountId: user.accountId,
|
||||||
|
userId: user.userId,
|
||||||
|
name: user.name,
|
||||||
|
role: user.role,
|
||||||
|
authorId: assignAuthorId,
|
||||||
|
email: user.email,
|
||||||
|
};
|
||||||
|
newUsersFileLines.push(newUser);
|
||||||
|
}
|
||||||
|
|
||||||
|
return newUsersFileLines;
|
||||||
|
} 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.transferDuplicateAuthor.name
|
||||||
|
}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -53,9 +53,11 @@ export class VerificationService {
|
|||||||
// 件数情報の取得
|
// 件数情報の取得
|
||||||
this.logger.log(`入力ファイルから件数情報を取得する`);
|
this.logger.log(`入力ファイルから件数情報を取得する`);
|
||||||
|
|
||||||
const accountCountFromFile = csvInputFiles.filter(
|
const accountFromFile = csvInputFiles.filter(
|
||||||
(item) => item.type !== "USER" && item.type !== "Country"
|
(item) => item.type !== "USER" && item.type !== "Country"
|
||||||
).length;
|
);
|
||||||
|
const accountCountFromFile = accountFromFile.length;
|
||||||
|
|
||||||
const cardLicensesCountFromFile = cardlicensesInputFiles.length;
|
const cardLicensesCountFromFile = cardlicensesInputFiles.length;
|
||||||
|
|
||||||
const licensesCountFromFile =
|
const licensesCountFromFile =
|
||||||
@ -66,18 +68,35 @@ export class VerificationService {
|
|||||||
|
|
||||||
// 管理ユーザ数のカウント
|
// 管理ユーザ数のカウント
|
||||||
const administratorCountFromFile = accountCountFromFile;
|
const administratorCountFromFile = accountCountFromFile;
|
||||||
|
|
||||||
// 一般ユーザ数のカウント
|
// 一般ユーザ数のカウント
|
||||||
const normaluserCountFromFile = csvInputFiles.filter(
|
// countryのアカウントに所属するユーザをカウント対象外とする
|
||||||
(item) => item.type === "USER" && item.user_email.length !== 0
|
const countryAccountFromFile = csvInputFiles.filter(
|
||||||
).length;
|
(item) => item.type === "Country"
|
||||||
|
);
|
||||||
|
|
||||||
|
// USER、かつuser_emailが設定なし、かつcountryのアカウントID以外をユーザとする
|
||||||
|
const normaluserFromFile = csvInputFiles.filter(
|
||||||
|
(item) =>
|
||||||
|
item.type === "USER" &&
|
||||||
|
item.user_email.length !== 0 &&
|
||||||
|
!countryAccountFromFile.some(
|
||||||
|
(countryItem) => countryItem.account_id === item.account_id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
const normaluserCountFromFile = normaluserFromFile.length;
|
||||||
|
|
||||||
// ユーザ重複数のカウント
|
// ユーザ重複数のカウント
|
||||||
let mailAdresses: string[] = [];
|
let mailAdresses: string[] = [];
|
||||||
csvInputFiles.forEach((item) => {
|
accountFromFile.forEach((item) => {
|
||||||
// メールアドレスの要素を配列に追加(入力データとして管理者とユーザの両方に入ることはない)
|
// メールアドレスの要素を配列に追加
|
||||||
if (item.email.length !== 0) {
|
if (item.email.length !== 0) {
|
||||||
mailAdresses.push(item.email);
|
mailAdresses.push(item.email);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
normaluserFromFile.forEach((item) => {
|
||||||
|
// メールアドレスの要素を配列に追加
|
||||||
if (item.user_email.length !== 0) {
|
if (item.user_email.length !== 0) {
|
||||||
mailAdresses.push(item.user_email);
|
mailAdresses.push(item.user_email);
|
||||||
}
|
}
|
||||||
@ -232,7 +251,11 @@ export class VerificationService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// dateを任意のフォーマットに変換する
|
// dateを任意のフォーマットに変換する
|
||||||
const getFormattedDate = (date: Date | null, format: string) => {
|
const getFormattedDate = (
|
||||||
|
date: Date | null,
|
||||||
|
format: string,
|
||||||
|
padHours: boolean = false // trueの場合、hhについてゼロパディングする(00→0、01→1、23→23)
|
||||||
|
) => {
|
||||||
if (!date) {
|
if (!date) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -244,9 +267,13 @@ const getFormattedDate = (date: Date | null, format: string) => {
|
|||||||
s: date.getSeconds(),
|
s: date.getSeconds(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// hhの値をゼロパディングするかどうかのフラグを確認
|
||||||
|
const hourSymbol = padHours ? "hh" : "h";
|
||||||
|
|
||||||
const formatted = format.replace(/(M+|d+|h+|m+|s+)/g, (v) =>
|
const formatted = format.replace(/(M+|d+|h+|m+|s+)/g, (v) =>
|
||||||
(
|
(
|
||||||
(v.length > 1 ? "0" : "") + symbol[v.slice(-1) as keyof typeof symbol]
|
(v.length > 1 && v !== hourSymbol ? "0" : "") +
|
||||||
|
symbol[v.slice(-1) as keyof typeof symbol]
|
||||||
).slice(-2)
|
).slice(-2)
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -542,12 +569,15 @@ function compareLicenses(
|
|||||||
VerificationResultDetails.push(VerificationResultDetailsOne);
|
VerificationResultDetails.push(VerificationResultDetailsOne);
|
||||||
isNoError = false;
|
isNoError = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// expiry_dateについて、時はゼロパディングした値で比較する(×01~09 ○1~9)
|
||||||
if (
|
if (
|
||||||
!licensesFromDatabase[i] ||
|
!licensesFromDatabase[i] ||
|
||||||
licensesFromFile[i].expired_date !==
|
licensesFromFile[i].expired_date !==
|
||||||
getFormattedDate(
|
getFormattedDate(
|
||||||
licensesFromDatabase[i].expiry_date,
|
licensesFromDatabase[i].expiry_date,
|
||||||
`yyyy/MM/dd hh:mm:ss`
|
`yyyy/MM/dd hh:mm:ss`,
|
||||||
|
true
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
const VerificationResultDetailsOne: VerificationResultDetails = {
|
const VerificationResultDetailsOne: VerificationResultDetails = {
|
||||||
@ -559,7 +589,8 @@ function compareLicenses(
|
|||||||
databaseData: licensesFromDatabase[i]
|
databaseData: licensesFromDatabase[i]
|
||||||
? getFormattedDate(
|
? getFormattedDate(
|
||||||
licensesFromDatabase[i].expiry_date,
|
licensesFromDatabase[i].expiry_date,
|
||||||
`yyyy/MM/dd hh:mm:ss`
|
`yyyy/MM/dd hh:mm:ss`,
|
||||||
|
true
|
||||||
)
|
)
|
||||||
: "undifined",
|
: "undifined",
|
||||||
reason: "内容不一致",
|
reason: "内容不一致",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user