diff --git a/dictation_server/src/features/accounts/accounts.service.ts b/dictation_server/src/features/accounts/accounts.service.ts index bad087b..76dfede 100644 --- a/dictation_server/src/features/accounts/accounts.service.ts +++ b/dictation_server/src/features/accounts/accounts.service.ts @@ -13,9 +13,9 @@ import { User } from '../../repositories/users/entity/user.entity'; import { TIERS, USER_ROLES, - ADB2C_SIGN_IN_TYPE, OPTION_ITEM_VALUE_TYPE, MANUAL_RECOVERY_REQUIRED, + LICENSE_ISSUE_STATUS, } from '../../constants'; import { makeErrorResponse } from '../../common/error/makeErrorResponse'; import { @@ -1106,13 +1106,55 @@ export class AccountsService { const myAccountId = ( await this.usersRepository.findUserByExternalId(context, userId) ).account_id; - await this.licensesRepository.issueLicense( + const { issuedOrderId } = await this.licensesRepository.issueLicense( context, orderedAccountId, myAccountId, tier, poNumber, ); + + try { + // 発行済みの注文をID指定して取得する + const orderLicense = await this.licensesRepository.getLicenseOrder( + context, + orderedAccountId, + poNumber, + issuedOrderId, + ); + + if (orderLicense == null) { + throw new Error( + `issue target order not found. fromAccountId: ${orderedAccountId}, poNumber:${poNumber}`, + ); + } + // 未発行の注文の場合、エラー + if (orderLicense.status !== LICENSE_ISSUE_STATUS.ISSUED) { + throw new AlreadyIssuedError( + `An order for PONumber:${poNumber} has not been issued.`, + ); + } + + // 注文したアカウントと自分のアカウントの情報を取得 + const customer = await this.getAccountInformation( + context, + orderedAccountId, + ); + const dealer = await this.getAccountInformation(context, myAccountId); + + await this.sendgridService.sendMailWithU107( + context, + customer.adminEmails, + customer.companyName, + orderLicense.quantity, + poNumber, + dealer.adminEmails, + dealer.companyName, + ); + } catch (e) { + this.logger.error(`[${context.getTrackingId()}] error=${e}`); + // メール送信に関する例外はログだけ出して握りつぶす + } } catch (e) { this.logger.error(`[${context.getTrackingId()}] error=${e}`); if (e instanceof Error) { @@ -2247,4 +2289,51 @@ export class AccountsService { ); } } + + /** + * アカウントIDを指定して、アカウント情報と管理者情報を取得する + * @param context + * @param accountId 対象アカウントID + * @returns 企業名/管理者メールアドレス + */ + private async getAccountInformation( + context: Context, + accountId: number, + ): Promise<{ + companyName: string; + adminEmails: string[]; + }> { + // アカウントIDから企業名を取得する + const { company_name } = await this.accountRepository.findAccountById( + context, + accountId, + ); + + // 管理者一覧を取得 + const admins = await this.usersRepository.findAdminUsers( + context, + accountId, + ); + const adminExternalIDs = admins.map((x) => x.external_id); + + // ADB2Cから管理者IDを元にメールアドレスを取得する + const usersInfo = await this.adB2cService.getUsers( + context, + adminExternalIDs, + ); + + // 生のAzure AD B2Cのユーザー情報からメールアドレスを抽出する + const adminEmails = usersInfo.map((x) => { + const { emailAddress } = getUserNameAndMailAddress(x); + if (emailAddress == null) { + throw new Error('dealer admin email-address is not found'); + } + return emailAddress; + }); + + return { + companyName: company_name, + adminEmails: adminEmails, + }; + } } diff --git a/dictation_server/src/gateways/sendgrid/sendgrid.service.ts b/dictation_server/src/gateways/sendgrid/sendgrid.service.ts index 5b1fb5a..5482611 100644 --- a/dictation_server/src/gateways/sendgrid/sendgrid.service.ts +++ b/dictation_server/src/gateways/sendgrid/sendgrid.service.ts @@ -25,6 +25,8 @@ export class SendGridService { private readonly templateU105Text: string; private readonly templateU106Html: string; private readonly templateU106Text: string; + private readonly templateU107Html: string; + private readonly templateU107Text: string; constructor(private readonly configService: ConfigService) { this.appDomain = this.configService.getOrThrow('APP_DOMAIN'); @@ -63,6 +65,15 @@ export class SendGridService { path.resolve(__dirname, `../../templates/template_U_106.txt`), 'utf-8', ); + + this.templateU107Html = readFileSync( + path.resolve(__dirname, `../../templates/template_U_107.html`), + 'utf-8', + ); + this.templateU107Text = readFileSync( + path.resolve(__dirname, `../../templates/template_U_107.txt`), + 'utf-8', + ); } } @@ -277,6 +288,61 @@ export class SendGridService { } } + /** + * U-107のテンプレートを使用したメールを送信する + * @param context + * @param cancelUserEmailAddress ライセンス発行をされたアカウントの管理者(primary/secondary)のメールアドレス + * @param customerAccountName 送信対象の企業名 + * @param lisenceCount ライセンス発行を行った対象の注文の内容(ライセンス数) + * @param poNumber ライセンス発行を行った対象の注文の内容(PO番号) + * @param dealerEmails 問題発生時に問い合わせする先の上位のディーラーの管理者(primary/secondary)のメールアドレス + * @param dealerAccountName 問題発生時に問い合わせする先の上位のディーラー名(会社名) + * @returns mail with u107 + */ + async sendMailWithU107( + context: Context, + customerMails: string[], + customerAccountName: string, + lisenceCount: number, + poNumber: string, + dealerEmails: string[], + dealerAccountName: string, + ): Promise { + this.logger.log( + `[IN] [${context.getTrackingId()}] ${this.sendMailWithU107.name}`, + ); + try { + const subject = 'License Issued Notification [U-107]'; + + // メールの本文を作成する + const html = this.templateU107Html + .replaceAll(CUSTOMER_NAME, customerAccountName) + .replaceAll(DEALER_NAME, dealerAccountName) + .replaceAll(PO_NUMBER, poNumber) + .replaceAll(LICENSE_QUANTITY, `${lisenceCount}`); + const text = this.templateU107Text + .replaceAll(CUSTOMER_NAME, customerAccountName) + .replaceAll(DEALER_NAME, dealerAccountName) + .replaceAll(PO_NUMBER, poNumber) + .replaceAll(LICENSE_QUANTITY, `${lisenceCount}`); + + // メールを送信する + this.sendMail( + context, + customerMails, + dealerEmails, + this.mailFrom, + subject, + text, + html, + ); + } finally { + this.logger.log( + `[OUT] [${context.getTrackingId()}] ${this.sendMailWithU107.name}`, + ); + } + } + /** * メールを送信する * @param context diff --git a/dictation_server/src/repositories/licenses/licenses.repository.service.ts b/dictation_server/src/repositories/licenses/licenses.repository.service.ts index 523f004..988e8c1 100644 --- a/dictation_server/src/repositories/licenses/licenses.repository.service.ts +++ b/dictation_server/src/repositories/licenses/licenses.repository.service.ts @@ -409,9 +409,9 @@ export class LicensesRepositoryService { myAccountId: number, tier: number, poNumber: string, - ): Promise { + ): Promise<{ issuedOrderId: number }> { const nowDate = new Date(); - await this.dataSource.transaction(async (entityManager) => { + return await this.dataSource.transaction(async (entityManager) => { const licenseOrderRepo = entityManager.getRepository(LicenseOrder); const licenseRepo = entityManager.getRepository(License); @@ -501,6 +501,8 @@ export class LicensesRepositoryService { context, ); } + + return { issuedOrderId: issuingOrder.id }; }); } /** diff --git a/dictation_server/src/templates/template_U_107.html b/dictation_server/src/templates/template_U_107.html new file mode 100644 index 0000000..638b841 --- /dev/null +++ b/dictation_server/src/templates/template_U_107.html @@ -0,0 +1,82 @@ + + + License Issued Notification [U-107] + + +
+

<English>

+

Dear $CUSTOMER_NAME$,

+

+ The ODMS Cloud licenses which you ordered has been issued.
+ - Number of Licenses Issued: $LICENSE_QUANTITY$
+ - PO Number: $PO_NUMBER$ +

+

+ In order to use ODMS Cloud, you will need to register your users in the + system and assign licenses to those users. When starting the app, please + log in to the system using your registered user's e-mail address and + password. +

+

+ If you need support regarding ODMS Cloud, please contact $DEALER_NAME$. +

+

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

+
+
+

<Deutsch>

+

Sehr geehrte(r) $CUSTOMER_NAME$,

+

+ Die von Ihnen bestellten ODMS Cloud-Lizenzen wurden ausgestellt.
+ - Anzahl der ausgestellten Lizenzen: $LICENSE_QUANTITY$
+ - Bestellnummer: $PO_NUMBER$ +

+

+ Um ODMS Cloud nutzen zu können, müssen Sie Ihre Benutzer im System + registrieren und diesen Benutzern Lizenzen zuweisen. Bitte melden Sie + sich beim Starten der App mit der E-Mail-Adresse und dem Passwort Ihres + registrierten Benutzers am System an. +

+

+ Wenn Sie Unterstützung bezüglich ODMS Cloud benötigen, wenden Sie sich + bitte an $DEALER_NAME$. +

+

+ Wenn Sie diese E-Mail fälschlicherweise erhalten haben, löschen Sie + diese E-Mail bitte aus Ihrem System.
+ Dies ist eine automatisch generierte E-Mail und dieses Postfach wird + nicht überwacht. Bitte nicht antworten. +

+
+
+

<Français>

+

Chère/Cher $CUSTOMER_NAME$,

+

+ Les licences ODMS Cloud que vous avez commandées ont été émises.
+ - Nombre de licences délivrées: $LICENSE_QUANTITY$
+ - Numéro de bon de commande: $PO_NUMBER$ +

+

+ Pour utiliser ODMS Cloud, vous devrez enregistrer vos utilisateurs dans + le système et attribuer des licences à ces utilisateurs. Lors du + démarrage de l'application, veuillez vous connecter au système en + utilisant l'adresse e-mail et le mot de passe de votre utilisateur + enregistré. +

+

+ Si vous avez besoin d'assistance concernant ODMS Cloud, veuillez + contacter $DEALER_NAME$. +

+

+ Si vous avez reçu cet e-mail par erreur, veuillez supprimer cet e-mail + de votre système.
+ Il s'agit d'un e-mail généré automatiquement et cette boîte aux lettres + n'est pas surveillée. Merci de ne pas répondre. +

+
+ + diff --git a/dictation_server/src/templates/template_U_107.txt b/dictation_server/src/templates/template_U_107.txt new file mode 100644 index 0000000..93914f7 --- /dev/null +++ b/dictation_server/src/templates/template_U_107.txt @@ -0,0 +1,44 @@ + + +Dear $CUSTOMER_NAME$, + +The ODMS Cloud licenses which you ordered has been issued. + - Number of Licenses Issued: $LICENSE_QUANTITY$ + - PO Number: $PO_NUMBER$ + +In order to use ODMS Cloud, you will need to register your users in the system and assign licenses to those users. When starting the app, please log in to the system using your registered user's e-mail address and password. + +If you need support regarding ODMS Cloud, please contact $DEALER_NAME$. + +If you have received this e-mail in error, please delete this e-mail from your system. +This is an automatically generated e-mail and this mailbox is not monitored. Please do not reply. + + + +Sehr geehrte(r) $CUSTOMER_NAME$, + +Die von Ihnen bestellten ODMS Cloud-Lizenzen wurden ausgestellt. + - Anzahl der ausgestellten Lizenzen: $LICENSE_QUANTITY$ + - Bestellnummer: $PO_NUMBER$ + +Um ODMS Cloud nutzen zu können, müssen Sie Ihre Benutzer im System registrieren und diesen Benutzern Lizenzen zuweisen. Bitte melden Sie sich beim Starten der App mit der E-Mail-Adresse und dem Passwort Ihres registrierten Benutzers am System an. + +Wenn Sie Unterstützung bezüglich ODMS Cloud benötigen, wenden Sie sich bitte an $DEALER_NAME$. + +Wenn Sie diese E-Mail fälschlicherweise erhalten haben, löschen Sie diese E-Mail bitte aus Ihrem System. +Dies ist eine automatisch generierte E-Mail und dieses Postfach wird nicht überwacht. Bitte nicht antworten. + + + +Chère/Cher $CUSTOMER_NAME$, + +Les licences ODMS Cloud que vous avez commandées ont été émises. + - Nombre de licences délivrées: $LICENSE_QUANTITY$ + - Numéro de bon de commande: $PO_NUMBER$ + +Pour utiliser ODMS Cloud, vous devrez enregistrer vos utilisateurs dans le système et attribuer des licences à ces utilisateurs. Lors du démarrage de l'application, veuillez vous connecter au système en utilisant l'adresse e-mail et le mot de passe de votre utilisateur enregistré. + +Si vous avez besoin d'assistance concernant ODMS Cloud, veuillez contacter $DEALER_NAME$. + +Si vous avez reçu cet e-mail par erreur, veuillez supprimer cet e-mail de votre système. +Il s'agit d'un e-mail généré automatiquement et cette boîte aux lettres n'est pas surveillée. Merci de ne pas répondre.