diff --git a/dictation_server/src/features/users/users.controller.ts b/dictation_server/src/features/users/users.controller.ts index 8d448d9..531c13b 100644 --- a/dictation_server/src/features/users/users.controller.ts +++ b/dictation_server/src/features/users/users.controller.ts @@ -1139,7 +1139,14 @@ export class UsersController { const context = makeContext(systemName, requestId); this.logger.log(`[${context.getTrackingId()}] ip : ${ip}`); - // TODO: 処理を実装 + const { accountId, filename, requestTime, errors } = body; + await this.usersService.multipleImportsComplate( + context, + accountId, + filename, + requestTime, + errors, + ); return {}; } diff --git a/dictation_server/src/features/users/users.service.spec.ts b/dictation_server/src/features/users/users.service.spec.ts index 5ecb653..26f9703 100644 --- a/dictation_server/src/features/users/users.service.spec.ts +++ b/dictation_server/src/features/users/users.service.spec.ts @@ -56,6 +56,8 @@ import { import { truncateAllTable } from '../../common/test/init'; import { createTask } from '../files/test/utility'; import { createCheckoutPermissions } from '../tasks/test/utility'; +import { SendGridService } from '../../gateways/sendgrid/sendgrid.service'; +import { MultipleImportErrors } from './types/types'; describe('UsersService.confirmUser', () => { let source: DataSource | null = null; @@ -3653,3 +3655,188 @@ describe('UsersService.deleteUser', () => { } }); }); + +describe('UsersService.multipleImportsComplate', () => { + let source: DataSource | null = null; + + beforeAll(async () => { + if (source == null) { + source = await (async () => { + const s = new DataSource({ + type: 'mysql', + host: 'test_mysql_db', + port: 3306, + username: 'user', + password: 'password', + database: 'odms', + entities: [__dirname + '/../../**/*.entity{.ts,.js}'], + synchronize: false, // trueにすると自動的にmigrationが行われるため注意 + }); + return await s.initialize(); + })(); + } + }); + + beforeEach(async () => { + if (source) { + await truncateAllTable(source); + } + }); + + afterAll(async () => { + await source?.destroy(); + source = null; + }); + + it('ユーザー一括登録完了メールを送信できる(成功)', async () => { + if (!source) fail(); + const module = await makeTestingModule(source); + if (!module) fail(); + + const { account: dealer } = await makeTestAccount(source, { + company_name: 'dealerCompany', + tier: 4, + }); + const { account, admin } = await makeTestAccount(source, { + tier: 5, + company_name: 'company', + parent_account_id: dealer.id, + }); + + const service = module.get(UsersService); + const context = makeContext(`uuidv4`, 'requestId'); + + overrideAdB2cService(service, { + getUsers: async () => { + return [ + { + id: admin.external_id, + displayName: 'admin', + identities: [ + { + signInType: ADB2C_SIGN_IN_TYPE.EMAILADDRESS, + issuer: 'issuer', + issuerAssignedId: 'admin@example.com', + }, + ], + }, + ]; + }, + }); + overrideSendgridService(service, {}); + // メール送信関数が呼ばれたかどうかで判定を行う。実際のメール送信は行わない。 + const spy = jest + .spyOn(service['sendgridService'], 'sendMailWithU121') + .mockImplementation(); + + const requestTime = Math.floor(new Date(2024, 2, 3).getTime() / 1000); + const filename = `U_20240303_000000_${admin.account_id}_${admin.id}.csv`; + const errors: MultipleImportErrors[] = []; + + // ユーザー一括登録完了 + await service.multipleImportsComplate( + context, + account.id, + filename, + requestTime, + errors, + ); + + // ADB2Cユーザー削除メソッドが呼ばれているか確認 + expect(spy).toHaveBeenCalledWith( + context, + ['admin@example.com'], + account.company_name, + dealer.company_name, + '2024.3.3', + filename, + ); + }); + + it('ユーザー一括登録完了メールを送信できる(失敗)', async () => { + if (!source) fail(); + const module = await makeTestingModule(source); + if (!module) fail(); + + const { account: dealer } = await makeTestAccount(source, { + company_name: 'dealerCompany', + tier: 4, + }); + const { account, admin } = await makeTestAccount(source, { + tier: 5, + company_name: 'company', + parent_account_id: dealer.id, + }); + + const service = module.get(UsersService); + const context = makeContext(`uuidv4`, 'requestId'); + + overrideAdB2cService(service, { + getUsers: async () => { + return [ + { + id: admin.external_id, + displayName: 'admin', + identities: [ + { + signInType: ADB2C_SIGN_IN_TYPE.EMAILADDRESS, + issuer: 'issuer', + issuerAssignedId: 'admin@example.com', + }, + ], + }, + ]; + }, + }); + overrideSendgridService(service, {}); + // メール送信関数が呼ばれたかどうかで判定を行う。実際のメール送信は行わない。 + const spy = jest + .spyOn(service['sendgridService'], 'sendMailWithU122') + .mockImplementation(); + + const requestTime = Math.floor(new Date(2024, 2, 3).getTime() / 1000); + const filename = `U_20240303_000000_${admin.account_id}_${admin.id}`; + const errors: MultipleImportErrors[] = [ + { + name: 'user1', + line: 1, + errorCode: 'E010301', + }, + { + name: 'user2', + line: 2, + errorCode: 'E010302', + }, + { + name: 'user2', + line: 3, + errorCode: 'E010302', + }, + { + name: 'user3', + line: 4, + errorCode: 'E009999', + }, + ]; + + // ユーザー一括登録完了 + await service.multipleImportsComplate( + context, + account.id, + filename, + requestTime, + errors, + ); + + // ADB2Cユーザー削除メソッドが呼ばれているか確認 + expect(spy).toHaveBeenCalledWith( + context, + ['admin@example.com'], + account.company_name, + dealer.company_name, + [1], + [2, 3], + [4], + ); + }); +}); diff --git a/dictation_server/src/features/users/users.service.ts b/dictation_server/src/features/users/users.service.ts index 1644a3c..2dbf943 100644 --- a/dictation_server/src/features/users/users.service.ts +++ b/dictation_server/src/features/users/users.service.ts @@ -23,7 +23,11 @@ import { } from '../../repositories/users/entity/user.entity'; import { UsersRepositoryService } from '../../repositories/users/users.repository.service'; import { LicensesRepositoryService } from '../../repositories/licenses/licenses.repository.service'; -import { GetRelationsResponse, User } from './types/types'; +import { + GetRelationsResponse, + MultipleImportErrors, + User, +} from './types/types'; import { AdminDeleteFailedError, AssignedWorkflowWithAuthorDeleteFailedError, @@ -1492,6 +1496,109 @@ export class UsersService { ); } } + /** + * ユーザー一括登録完了メールを送信する + * @param context + * @param accountId + * @param fileName + * @param requestTime + * @param errors + * @returns imports complate + */ + async multipleImportsComplate( + context: Context, + accountId: number, + fileName: string, + requestTime: number, + errors: MultipleImportErrors[], + ): Promise { + this.logger.log( + `[IN] [${context.getTrackingId()}] ${ + this.multipleImportsComplate.name + } | params: { accountId: ${accountId}, fileName: ${fileName}, requestTime: ${requestTime} };`, + ); + try { + const account = await this.accountsRepository.findAccountById( + context, + accountId, + ); + if (!account) { + throw new Error(`account not found. id=${accountId}`); + } + + const dealerId = account.parent_account_id; + let dealerName: string | null = null; + if (dealerId !== null) { + const { company_name } = await this.accountsRepository.findAccountById( + context, + dealerId, + ); + dealerName = company_name; + } + + // アカウント情報を取得 + const { companyName, adminEmails } = await this.getAccountInformation( + context, + accountId, + ); + + if (errors.length === 0) { + const requestTimeDate = new Date(requestTime * 1000); + + // 完了メールを通知する + await this.sendgridService.sendMailWithU121( + context, + adminEmails, + companyName, + dealerName, + `${requestTimeDate.getFullYear()}.${ + requestTimeDate.getMonth() + 1 + }.${requestTimeDate.getDate()}`, + fileName, + ); + } else { + const duplicateEmails: number[] = []; + const duplicateAuthorIds: number[] = []; + const otherErrors: number[] = []; + // エラーを仕分ける + for (const error of errors) { + switch (error.errorCode) { + // メールアドレス重複エラー + case 'E010301': + duplicateEmails.push(error.line); + break; + // AuthorID重複エラー + case 'E010302': + duplicateAuthorIds.push(error.line); + break; + // その他エラー + default: + otherErrors.push(error.line); + break; + } + } + + // エラーメールを通知する + await this.sendgridService.sendMailWithU122( + context, + adminEmails, + companyName, + dealerName, + duplicateEmails, + duplicateAuthorIds, + otherErrors, + ); + } + } catch (e) { + this.logger.error(`[${context.getTrackingId()}] error=${e}`); + } finally { + this.logger.log( + `[OUT] [${context.getTrackingId()}] ${ + this.multipleImportsComplate.name + }`, + ); + } + } /** * アカウントIDを指定して、アカウント情報と管理者情報を取得する diff --git a/dictation_server/src/gateways/sendgrid/sendgrid.service.ts b/dictation_server/src/gateways/sendgrid/sendgrid.service.ts index ea80ba7..bfc1064 100644 --- a/dictation_server/src/gateways/sendgrid/sendgrid.service.ts +++ b/dictation_server/src/gateways/sendgrid/sendgrid.service.ts @@ -20,6 +20,10 @@ import { TYPIST_NAME, VERIFY_LINK, TEMPORARY_PASSWORD, + EMAIL_DUPLICATION, + AUTHOR_ID_DUPLICATION, + UNEXPECTED_ERROR, + REQUEST_TIME, } from '../../templates/constants'; import { URL } from 'node:url'; @@ -71,6 +75,14 @@ export class SendGridService { private readonly templateU119Text: string; private readonly templateU119NoParentHtml: string; private readonly templateU119NoParentText: string; + private readonly templateU121Html: string; + private readonly templateU121Text: string; + private readonly templateU121NoParentHtml: string; + private readonly templateU121NoParentText: string; + private readonly templateU122Html: string; + private readonly templateU122Text: string; + private readonly templateU122NoParentHtml: string; + private readonly templateU122NoParentText: string; constructor(private readonly configService: ConfigService) { this.appDomain = this.configService.getOrThrow('APP_DOMAIN'); @@ -255,6 +267,44 @@ export class SendGridService { path.resolve(__dirname, `../../templates/template_U_119_no_parent.txt`), 'utf-8', ); + this.templateU121Html = readFileSync( + path.resolve(__dirname, `../../templates/template_U_121.html`), + 'utf-8', + ); + this.templateU121Text = readFileSync( + path.resolve(__dirname, `../../templates/template_U_121.txt`), + 'utf-8', + ); + this.templateU121NoParentHtml = readFileSync( + path.resolve( + __dirname, + `../../templates/template_U_121_no_parent.html`, + ), + 'utf-8', + ); + this.templateU121NoParentText = readFileSync( + path.resolve(__dirname, `../../templates/template_U_121_no_parent.txt`), + 'utf-8', + ); + this.templateU122Html = readFileSync( + path.resolve(__dirname, `../../templates/template_U_122.html`), + 'utf-8', + ); + this.templateU122Text = readFileSync( + path.resolve(__dirname, `../../templates/template_U_122.txt`), + 'utf-8', + ); + this.templateU122NoParentHtml = readFileSync( + path.resolve( + __dirname, + `../../templates/template_U_122_no_parent.html`, + ), + 'utf-8', + ); + this.templateU122NoParentText = readFileSync( + path.resolve(__dirname, `../../templates/template_U_122_no_parent.txt`), + 'utf-8', + ); } } @@ -1138,6 +1188,157 @@ export class SendGridService { } } + /** + * U-121のテンプレートを使用したメールを送信する + * @param context + * @param customerAdminMails アカウントの管理者(primary/secondary)のメールアドレス + * @param customerAccountName アカウントの名前 + * @param dealerAccountName 問題発生時に問い合わせする先の上位のディーラー名(会社名) + * @param requestTime ユーザー一括登録のリクエストを受け付けた日時 + * @param fileName ユーザー一括登録で使用されたファイル名 + * @returns mail with u121 + */ + async sendMailWithU121( + context: Context, + customerAdminMails: string[], + customerAccountName: string, + dealerAccountName: string | null, + requestTime: string, + fileName: string, + ): Promise { + this.logger.log( + `[IN] [${context.getTrackingId()}] ${this.sendMailWithU121.name}`, + ); + try { + const subject = 'ユーザー一括登録 完了通知 [U-121]'; + + let html: string; + let text: string; + + if (!dealerAccountName) { + html = this.templateU121NoParentHtml + .replaceAll(CUSTOMER_NAME, customerAccountName) + .replaceAll(REQUEST_TIME, requestTime) + .replaceAll(FILE_NAME, fileName); + text = this.templateU121NoParentText + .replaceAll(CUSTOMER_NAME, customerAccountName) + .replaceAll(REQUEST_TIME, requestTime) + .replaceAll(FILE_NAME, fileName); + } else { + html = this.templateU121Html + .replaceAll(CUSTOMER_NAME, customerAccountName) + .replaceAll(DEALER_NAME, dealerAccountName) + .replaceAll(REQUEST_TIME, requestTime) + .replaceAll(FILE_NAME, fileName); + text = this.templateU121Text + .replaceAll(CUSTOMER_NAME, customerAccountName) + .replaceAll(DEALER_NAME, dealerAccountName) + .replaceAll(REQUEST_TIME, requestTime) + .replaceAll(FILE_NAME, fileName); + } + + // メールを送信する + await this.sendMail( + context, + customerAdminMails, + [], + this.mailFrom, + subject, + text, + html, + ); + } finally { + this.logger.log( + `[OUT] [${context.getTrackingId()}] ${this.sendMailWithU121.name}`, + ); + } + } + + /** + * U-122のテンプレートを使用したメールを送信する + * @param context + * @param customerAdminMails アカウントの管理者(primary/secondary)のメールアドレス + * @param customerAccountName アカウントの名前 + * @param dealerAccountName 問題発生時に問い合わせする先の上位のディーラー名(会社名) + * @param duplicateEmails メールアドレスの重複エラーのある行番号 + * @param duplicateAuthorIds AuthorIdの重複エラーのある行番号 + * @param otherErrors その他のエラーのある行番号 + * @returns mail with u122 + */ + async sendMailWithU122( + context: Context, + customerAdminMails: string[], + customerAccountName: string, + dealerAccountName: string | null, + duplicateEmails: number[], + duplicateAuthorIds: number[], + otherErrors: number[], + ): Promise { + this.logger.log( + `[IN] [${context.getTrackingId()}] ${this.sendMailWithU122.name}`, + ); + try { + const duplicateEmailsMsg = + duplicateEmails.length === 0 + ? 'エラーはありません' + : duplicateEmails.map((x) => `L${x}`).join(', '); + const duplicateAuthorIdsMsg = + duplicateAuthorIds.length === 0 + ? 'エラーはありません' + : duplicateAuthorIds.map((x) => `L${x}`).join(', '); + const otherErrorsMsg = + otherErrors.length === 0 + ? 'エラーはありません' + : otherErrors.map((x) => `L${x}`).join(', '); + + const subject = 'ユーザー一括登録 失敗通知 [U-122]'; + + let html: string; + let text: string; + + if (!dealerAccountName) { + html = this.templateU122NoParentHtml + .replaceAll(CUSTOMER_NAME, customerAccountName) + .replaceAll(EMAIL_DUPLICATION, duplicateEmailsMsg) + .replaceAll(AUTHOR_ID_DUPLICATION, duplicateAuthorIdsMsg) + .replaceAll(UNEXPECTED_ERROR, otherErrorsMsg); + text = this.templateU122NoParentText + .replaceAll(CUSTOMER_NAME, customerAccountName) + .replaceAll(EMAIL_DUPLICATION, duplicateEmailsMsg) + .replaceAll(AUTHOR_ID_DUPLICATION, duplicateAuthorIdsMsg) + .replaceAll(UNEXPECTED_ERROR, otherErrorsMsg); + } else { + html = this.templateU122Html + .replaceAll(CUSTOMER_NAME, customerAccountName) + .replaceAll(DEALER_NAME, dealerAccountName) + .replaceAll(EMAIL_DUPLICATION, duplicateEmailsMsg) + .replaceAll(AUTHOR_ID_DUPLICATION, duplicateAuthorIdsMsg) + .replaceAll(UNEXPECTED_ERROR, otherErrorsMsg); + text = this.templateU122Text + .replaceAll(CUSTOMER_NAME, customerAccountName) + .replaceAll(DEALER_NAME, dealerAccountName) + .replaceAll(EMAIL_DUPLICATION, duplicateEmailsMsg) + .replaceAll(AUTHOR_ID_DUPLICATION, duplicateAuthorIdsMsg) + .replaceAll(UNEXPECTED_ERROR, otherErrorsMsg); + } + + // メールを送信する + await this.sendMail( + context, + customerAdminMails, + [], + this.mailFrom, + subject, + text, + html, + ); + } finally { + this.logger.log( + `[OUT] [${context.getTrackingId()}] ${this.sendMailWithU122.name}`, + ); + } + } + /** * メールを送信する * @param context diff --git a/dictation_server/src/templates/constants.ts b/dictation_server/src/templates/constants.ts index 72e8fc0..319bed8 100644 --- a/dictation_server/src/templates/constants.ts +++ b/dictation_server/src/templates/constants.ts @@ -11,3 +11,8 @@ export const AUTHOR_NAME = '$AUTHOR_NAME$'; export const FILE_NAME = '$FILE_NAME$'; export const TYPIST_NAME = '$TYPIST_NAME$'; export const TEMPORARY_PASSWORD = '$TEMPORARY_PASSWORD$'; +export const REQUEST_TIME = '$REQUEST_TIME$'; + +export const EMAIL_DUPLICATION = `$EMAIL_DUPLICATION$`; +export const AUTHOR_ID_DUPLICATION = `$AUTHOR_ID_DUPLICATION$`; +export const UNEXPECTED_ERROR = `$UNEXPECTED_ERROR$`; diff --git a/dictation_server/src/templates/template_U_121.html b/dictation_server/src/templates/template_U_121.html new file mode 100644 index 0000000..957b7ae --- /dev/null +++ b/dictation_server/src/templates/template_U_121.html @@ -0,0 +1,65 @@ + + + Storage Usage Exceeded Notification [U-119] + + + +
+

<English>

+

Dear $CUSTOMER_NAME$,

+

ODMS Cloudをご利用いただきありがとうございます。

+

+ CSVファイルによるユーザー一括登録が完了しました。
+ - リクエスト日時:$REQUEST_TIME$
+ - SCVファイル名:$FILE_NAME$ +

+

+ ディーラーによるサポートが必要な場合は、 $DEALER_NAME$ + にお問い合わせください。 +

+

+ If you received this e-mail in error, please delete this e-mail from + your system.
+ This is an automatically generated e-mail, please do not reply. +

+
+
+

<Deutsch>

+

Dear $CUSTOMER_NAME$,

+

ODMS Cloudをご利用いただきありがとうございます。

+

+ CSVファイルによるユーザー一括登録が完了しました。
+ - リクエスト日時:$REQUEST_TIME$
+ - SCVファイル名:$FILE_NAME$ +

+

+ ディーラーによるサポートが必要な場合は、 $DEALER_NAME$ + にお問い合わせください。 +

+

+ If you received this e-mail in error, please delete this e-mail from + your system.
+ This is an automatically generated e-mail, please do not reply. +

+
+
+

<Français>

+

Dear $CUSTOMER_NAME$,

+

ODMS Cloudをご利用いただきありがとうございます。

+

+ CSVファイルによるユーザー一括登録が完了しました。
+ - リクエスト日時:$REQUEST_TIME$
+ - SCVファイル名:$FILE_NAME$ +

+

+ ディーラーによるサポートが必要な場合は、 $DEALER_NAME$ + にお問い合わせください。 +

+

+ If you received this e-mail in error, please delete this e-mail from + your system.
+ This is an automatically generated e-mail, please do not reply. +

+
+ + diff --git a/dictation_server/src/templates/template_U_121.txt b/dictation_server/src/templates/template_U_121.txt new file mode 100644 index 0000000..f1995de --- /dev/null +++ b/dictation_server/src/templates/template_U_121.txt @@ -0,0 +1,44 @@ + + +Dear $CUSTOMER_NAME$, + +ODMS Cloudをご利用いただきありがとうございます。 + +CSVファイルによるユーザー一括登録が完了しました。 + - リクエスト日時:$REQUEST_TIME$ + - SCVファイル名:$FILE_NAME$ + +ディーラーによるサポートが必要な場合は、 $DEALER_NAME$ にお問い合わせください。 + +If you received this e-mail in error, please delete this e-mail from your system. +This is an automatically generated e-mail, please do not reply. + + + +Dear $CUSTOMER_NAME$, + +ODMS Cloudをご利用いただきありがとうございます。 + +CSVファイルによるユーザー一括登録が完了しました。 + - リクエスト日時:$REQUEST_TIME$ + - SCVファイル名:$FILE_NAME$ + +ディーラーによるサポートが必要な場合は、 $DEALER_NAME$ にお問い合わせください。 + +If you received this e-mail in error, please delete this e-mail from your system. +This is an automatically generated e-mail, please do not reply. + + + +Dear $CUSTOMER_NAME$, + +ODMS Cloudをご利用いただきありがとうございます。 + +CSVファイルによるユーザー一括登録が完了しました。 + - リクエスト日時:$REQUEST_TIME$ + - SCVファイル名:$FILE_NAME$ + +ディーラーによるサポートが必要な場合は、 $DEALER_NAME$ にお問い合わせください。 + +If you received this e-mail in error, please delete this e-mail from your system. +This is an automatically generated e-mail, please do not reply. \ No newline at end of file diff --git a/dictation_server/src/templates/template_U_121_no_parent.html b/dictation_server/src/templates/template_U_121_no_parent.html new file mode 100644 index 0000000..0ae8b99 --- /dev/null +++ b/dictation_server/src/templates/template_U_121_no_parent.html @@ -0,0 +1,53 @@ + + + Storage Usage Exceeded Notification [U-119] + + + +
+

<English>

+

Dear $CUSTOMER_NAME$,

+

ODMS Cloudをご利用いただきありがとうございます。

+

+ CSVファイルによるユーザー一括登録が完了しました。
+ - リクエスト日時:$REQUEST_TIME$
+ - SCVファイル名:$FILE_NAME$ +

+

+ If you received this e-mail in error, please delete this e-mail from + your system.
+ This is an automatically generated e-mail, please do not reply. +

+
+
+

<Deutsch>

+

Dear $CUSTOMER_NAME$,

+

ODMS Cloudをご利用いただきありがとうございます。

+

+ CSVファイルによるユーザー一括登録が完了しました。
+ - リクエスト日時:$REQUEST_TIME$
+ - SCVファイル名:$FILE_NAME$ +

+

+ If you received this e-mail in error, please delete this e-mail from + your system.
+ This is an automatically generated e-mail, please do not reply. +

+
+
+

<Français>

+

Dear $CUSTOMER_NAME$,

+

ODMS Cloudをご利用いただきありがとうございます。

+

+ CSVファイルによるユーザー一括登録が完了しました。
+ - リクエスト日時:$REQUEST_TIME$
+ - SCVファイル名:$FILE_NAME$ +

+

+ If you received this e-mail in error, please delete this e-mail from + your system.
+ This is an automatically generated e-mail, please do not reply. +

+
+ + diff --git a/dictation_server/src/templates/template_U_121_no_parent.txt b/dictation_server/src/templates/template_U_121_no_parent.txt new file mode 100644 index 0000000..cc81ddf --- /dev/null +++ b/dictation_server/src/templates/template_U_121_no_parent.txt @@ -0,0 +1,38 @@ + + +Dear $CUSTOMER_NAME$, + +ODMS Cloudをご利用いただきありがとうございます。 + +CSVファイルによるユーザー一括登録が完了しました。 + - リクエスト日時:$REQUEST_TIME$ + - SCVファイル名:$FILE_NAME$ + +If you received this e-mail in error, please delete this e-mail from your system. +This is an automatically generated e-mail, please do not reply. + + + +Dear $CUSTOMER_NAME$, + +ODMS Cloudをご利用いただきありがとうございます。 + +CSVファイルによるユーザー一括登録が完了しました。 + - リクエスト日時:$REQUEST_TIME$ + - SCVファイル名:$FILE_NAME$ + +If you received this e-mail in error, please delete this e-mail from your system. +This is an automatically generated e-mail, please do not reply. + + + +Dear $CUSTOMER_NAME$, + +ODMS Cloudをご利用いただきありがとうございます。 + +CSVファイルによるユーザー一括登録が完了しました。 + - リクエスト日時:$REQUEST_TIME$ + - SCVファイル名:$FILE_NAME$ + +If you received this e-mail in error, please delete this e-mail from your system. +This is an automatically generated e-mail, please do not reply. \ No newline at end of file diff --git a/dictation_server/src/templates/template_U_122.html b/dictation_server/src/templates/template_U_122.html new file mode 100644 index 0000000..7a5de32 --- /dev/null +++ b/dictation_server/src/templates/template_U_122.html @@ -0,0 +1,107 @@ + + + Storage Usage Exceeded Notification [U-119] + + + +
+

<English>

+

Dear $CUSTOMER_NAME$,

+

ODMS Cloudをご利用いただきありがとうございます。

+

CSVファイルによるユーザー一括登録に失敗しました。

+

+ 1. 以下の行にあるE-mail addressは既に登録済みか、別の行のE-mail + addressと重複しています。
+ $EMAIL_DUPLICATION$ +

+

+ 2. + 以下の行にあるAuthorIDは既に登録済みか、別の行のAuthorIDと重複しています。
+ $AUTHOR_ID_DUPLICATION$ +

+

+ *既に登録済みのE-mail address, Author IDを再登録することはできません。 +

+

+ 3. + 以下の行のユーザー登録時に想定外のエラーが発生しました。時間をおいて再度実行しても成功しない場合はディーラーにお問い合わせください。
+ $UNEXPECTED_ERROR$ +

+

+ ディーラーによるサポートが必要な場合は、 $DEALER_NAME$ + にお問い合わせください。 +

+

+ If you received this e-mail in error, please delete this e-mail from + your system. This is an automatically generated e-mail, please do not + reply. +

+
+
+

<Deutsch>

+

Dear $CUSTOMER_NAME$,

+

ODMS Cloudをご利用いただきありがとうございます。

+

CSVファイルによるユーザー一括登録に失敗しました。

+

+ 1. 以下の行にあるE-mail addressは既に登録済みか、別の行のE-mail + addressと重複しています。
+ $EMAIL_DUPLICATION$ +

+

+ 2. + 以下の行にあるAuthorIDは既に登録済みか、別の行のAuthorIDと重複しています。
+ $AUTHOR_ID_DUPLICATION$ +

+

+ *既に登録済みのE-mail address, Author IDを再登録することはできません。 +

+

+ 3. + 以下の行のユーザー登録時に想定外のエラーが発生しました。時間をおいて再度実行しても成功しない場合はディーラーにお問い合わせください。
+ $UNEXPECTED_ERROR$ +

+

+ ディーラーによるサポートが必要な場合は、 $DEALER_NAME$ + にお問い合わせください。 +

+

+ If you received this e-mail in error, please delete this e-mail from + your system. This is an automatically generated e-mail, please do not + reply. +

+
+
+

<Français>

+

Dear $CUSTOMER_NAME$,

+

ODMS Cloudをご利用いただきありがとうございます。

+

CSVファイルによるユーザー一括登録に失敗しました。

+

+ 1. 以下の行にあるE-mail addressは既に登録済みか、別の行のE-mail + addressと重複しています。
+ $EMAIL_DUPLICATION$ +

+

+ 2. + 以下の行にあるAuthorIDは既に登録済みか、別の行のAuthorIDと重複しています。
+ $AUTHOR_ID_DUPLICATION$ +

+

+ *既に登録済みのE-mail address, Author IDを再登録することはできません。 +

+

+ 3. + 以下の行のユーザー登録時に想定外のエラーが発生しました。時間をおいて再度実行しても成功しない場合はディーラーにお問い合わせください。
+ $UNEXPECTED_ERROR$ +

+

+ ディーラーによるサポートが必要な場合は、 $DEALER_NAME$ + にお問い合わせください。 +

+

+ If you received this e-mail in error, please delete this e-mail from + your system. This is an automatically generated e-mail, please do not + reply. +

+
+ + diff --git a/dictation_server/src/templates/template_U_122.txt b/dictation_server/src/templates/template_U_122.txt new file mode 100644 index 0000000..f4f2710 --- /dev/null +++ b/dictation_server/src/templates/template_U_122.txt @@ -0,0 +1,74 @@ + + +Dear $CUSTOMER_NAME$, + +ODMS Cloudをご利用いただきありがとうございます。 + +CSVファイルによるユーザー一括登録に失敗しました。 + + 1. 以下の行にあるE-mail addressは既に登録済みか、別の行のE-mail addressと重複しています。 + $EMAIL_DUPLICATION$ + + 2. 以下の行にあるAuthorIDは既に登録済みか、別の行のAuthorIDと重複しています。 + $AUTHOR_ID_DUPLICATION$ + + *既に登録済みのE-mail address, Author IDを再登録することはできません。 + + + 3. 以下の行のユーザー登録時に想定外のエラーが発生しました。時間をおいて再度実行しても成功しない場合はディーラーにお問い合わせください。 +   $UNEXPECTED_ERROR$ + +ディーラーによるサポートが必要な場合は、 $DEALER_NAME$ にお問い合わせください。 + +If you received this e-mail in error, please delete this e-mail from your system. +This is an automatically generated e-mail, please do not reply. + + + +Dear $CUSTOMER_NAME$, + +ODMS Cloudをご利用いただきありがとうございます。 + +CSVファイルによるユーザー一括登録に失敗しました。 + + 1. 以下の行にあるE-mail addressは既に登録済みか、別の行のE-mail addressと重複しています。 + $EMAIL_DUPLICATION$ + + 2. 以下の行にあるAuthorIDは既に登録済みか、別の行のAuthorIDと重複しています。 + $AUTHOR_ID_DUPLICATION$ + + *既に登録済みのE-mail address, Author IDを再登録することはできません。 + + + 3. 以下の行のユーザー登録時に想定外のエラーが発生しました。時間をおいて再度実行しても成功しない場合はディーラーにお問い合わせください。 +   $UNEXPECTED_ERROR$ + +ディーラーによるサポートが必要な場合は、 $DEALER_NAME$ にお問い合わせください。 + +If you received this e-mail in error, please delete this e-mail from your system. +This is an automatically generated e-mail, please do not reply. + + + +Dear $CUSTOMER_NAME$, + +ODMS Cloudをご利用いただきありがとうございます。 + +CSVファイルによるユーザー一括登録に失敗しました。 + + 1. 以下の行にあるE-mail addressは既に登録済みか、別の行のE-mail addressと重複しています。 + $EMAIL_DUPLICATION$ + + 2. 以下の行にあるAuthorIDは既に登録済みか、別の行のAuthorIDと重複しています。 + $AUTHOR_ID_DUPLICATION$ + + *既に登録済みのE-mail address, Author IDを再登録することはできません。 + + + 3. 以下の行のユーザー登録時に想定外のエラーが発生しました。時間をおいて再度実行しても成功しない場合はディーラーにお問い合わせください。 +   $UNEXPECTED_ERROR$ + +ディーラーによるサポートが必要な場合は、 $DEALER_NAME$ にお問い合わせください。 + +If you received this e-mail in error, please delete this e-mail from your system. +This is an automatically generated e-mail, please do not reply. \ No newline at end of file diff --git a/dictation_server/src/templates/template_U_122_no_parent.html b/dictation_server/src/templates/template_U_122_no_parent.html new file mode 100644 index 0000000..cac57e5 --- /dev/null +++ b/dictation_server/src/templates/template_U_122_no_parent.html @@ -0,0 +1,95 @@ + + + Storage Usage Exceeded Notification [U-119] + + + +
+

<English>

+

Dear $CUSTOMER_NAME$,

+

ODMS Cloudをご利用いただきありがとうございます。

+

CSVファイルによるユーザー一括登録に失敗しました。

+

+ 1. 以下の行にあるE-mail addressは既に登録済みか、別の行のE-mail + addressと重複しています。
+ $EMAIL_DUPLICATION$ +

+

+ 2. + 以下の行にあるAuthorIDは既に登録済みか、別の行のAuthorIDと重複しています。
+ $AUTHOR_ID_DUPLICATION$ +

+

+ *既に登録済みのE-mail address, Author IDを再登録することはできません。 +

+

+ 3. + 以下の行のユーザー登録時に想定外のエラーが発生しました。時間をおいて再度実行しても成功しない場合はディーラーにお問い合わせください。
+ $UNEXPECTED_ERROR$ +

+

+ If you received this e-mail in error, please delete this e-mail from + your system. This is an automatically generated e-mail, please do not + reply. +

+
+
+

<Deutsch>

+

Dear $CUSTOMER_NAME$,

+

ODMS Cloudをご利用いただきありがとうございます。

+

CSVファイルによるユーザー一括登録に失敗しました。

+

+ 1. 以下の行にあるE-mail addressは既に登録済みか、別の行のE-mail + addressと重複しています。
+ $EMAIL_DUPLICATION$ +

+

+ 2. + 以下の行にあるAuthorIDは既に登録済みか、別の行のAuthorIDと重複しています。
+ $AUTHOR_ID_DUPLICATION$ +

+

+ *既に登録済みのE-mail address, Author IDを再登録することはできません。 +

+

+ 3. + 以下の行のユーザー登録時に想定外のエラーが発生しました。時間をおいて再度実行しても成功しない場合はディーラーにお問い合わせください。
+ $UNEXPECTED_ERROR$ +

+

+ If you received this e-mail in error, please delete this e-mail from + your system. This is an automatically generated e-mail, please do not + reply. +

+
+
+

<Français>

+

Dear $CUSTOMER_NAME$,

+

ODMS Cloudをご利用いただきありがとうございます。

+

CSVファイルによるユーザー一括登録に失敗しました。

+

+ 1. 以下の行にあるE-mail addressは既に登録済みか、別の行のE-mail + addressと重複しています。
+ $EMAIL_DUPLICATION$ +

+

+ 2. + 以下の行にあるAuthorIDは既に登録済みか、別の行のAuthorIDと重複しています。
+ $AUTHOR_ID_DUPLICATION$ +

+

+ *既に登録済みのE-mail address, Author IDを再登録することはできません。 +

+

+ 3. + 以下の行のユーザー登録時に想定外のエラーが発生しました。時間をおいて再度実行しても成功しない場合はディーラーにお問い合わせください。
+ $UNEXPECTED_ERROR$ +

+

+ If you received this e-mail in error, please delete this e-mail from + your system. This is an automatically generated e-mail, please do not + reply. +

+
+ + diff --git a/dictation_server/src/templates/template_U_122_no_parent.txt b/dictation_server/src/templates/template_U_122_no_parent.txt new file mode 100644 index 0000000..3b54d39 --- /dev/null +++ b/dictation_server/src/templates/template_U_122_no_parent.txt @@ -0,0 +1,68 @@ + + +Dear $CUSTOMER_NAME$, + +ODMS Cloudをご利用いただきありがとうございます。 + +CSVファイルによるユーザー一括登録に失敗しました。 + + 1. 以下の行にあるE-mail addressは既に登録済みか、別の行のE-mail addressと重複しています。 + $EMAIL_DUPLICATION$ + + 2. 以下の行にあるAuthorIDは既に登録済みか、別の行のAuthorIDと重複しています。 + $AUTHOR_ID_DUPLICATION$ + + *既に登録済みのE-mail address, Author IDを再登録することはできません。 + + + 3. 以下の行のユーザー登録時に想定外のエラーが発生しました。時間をおいて再度実行しても成功しない場合はディーラーにお問い合わせください。 +   $UNEXPECTED_ERROR$ + +If you received this e-mail in error, please delete this e-mail from your system. +This is an automatically generated e-mail, please do not reply. + + + +Dear $CUSTOMER_NAME$, + +ODMS Cloudをご利用いただきありがとうございます。 + +CSVファイルによるユーザー一括登録に失敗しました。 + + 1. 以下の行にあるE-mail addressは既に登録済みか、別の行のE-mail addressと重複しています。 + $EMAIL_DUPLICATION$ + + 2. 以下の行にあるAuthorIDは既に登録済みか、別の行のAuthorIDと重複しています。 + $AUTHOR_ID_DUPLICATION$ + + *既に登録済みのE-mail address, Author IDを再登録することはできません。 + + + 3. 以下の行のユーザー登録時に想定外のエラーが発生しました。時間をおいて再度実行しても成功しない場合はディーラーにお問い合わせください。 +   $UNEXPECTED_ERROR$ + +If you received this e-mail in error, please delete this e-mail from your system. +This is an automatically generated e-mail, please do not reply. + + + +Dear $CUSTOMER_NAME$, + +ODMS Cloudをご利用いただきありがとうございます。 + +CSVファイルによるユーザー一括登録に失敗しました。 + + 1. 以下の行にあるE-mail addressは既に登録済みか、別の行のE-mail addressと重複しています。 + $EMAIL_DUPLICATION$ + + 2. 以下の行にあるAuthorIDは既に登録済みか、別の行のAuthorIDと重複しています。 + $AUTHOR_ID_DUPLICATION$ + + *既に登録済みのE-mail address, Author IDを再登録することはできません。 + + + 3. 以下の行のユーザー登録時に想定外のエラーが発生しました。時間をおいて再度実行しても成功しない場合はディーラーにお問い合わせください。 +   $UNEXPECTED_ERROR$ + +If you received this e-mail in error, please delete this e-mail from your system. +This is an automatically generated e-mail, please do not reply. \ No newline at end of file