Merged PR 639: ライセンス発行完了通知 [U-107] の実装

## 概要
[Task3304: ライセンス発行完了通知 [U-107] の実装](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/3304)

- ライセンス発行完了時のメール送信機能を追加しました。

## レビューポイント
- テンプレートの内容は適切でしょうか?
- メールに渡す値の取得で不自然な点はないでしょうか?

## UIの変更
- なし

## 動作確認状況
- ローカルで確認
This commit is contained in:
makabe.t 2023-12-19 01:25:57 +00:00
parent 4d325d1751
commit 11aa73f190
5 changed files with 287 additions and 4 deletions

View File

@ -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,
};
}
}

View File

@ -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<string>('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<void> {
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

View File

@ -409,9 +409,9 @@ export class LicensesRepositoryService {
myAccountId: number,
tier: number,
poNumber: string,
): Promise<void> {
): 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 };
});
}
/**

View File

@ -0,0 +1,82 @@
<html>
<head>
<title>License Issued Notification [U-107]</title>
</head>
<body>
<div>
<h3>&lt;English&gt;</h3>
<p>Dear $CUSTOMER_NAME$,</p>
<p>
The ODMS Cloud licenses which you ordered has been issued.<br />
- Number of Licenses Issued: $LICENSE_QUANTITY$<br />
- PO Number: $PO_NUMBER$
</p>
<p>
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.
</p>
<p>
If you need support regarding ODMS Cloud, please contact $DEALER_NAME$.
</p>
<p>
If you have received this e-mail in error, please delete this e-mail
from your system.<br />
This is an automatically generated e-mail and this mailbox is not
monitored. Please do not reply.
</p>
</div>
<div>
<h3>&lt;Deutsch&gt;</h3>
<p>Sehr geehrte(r) $CUSTOMER_NAME$,</p>
<p>
Die von Ihnen bestellten ODMS Cloud-Lizenzen wurden ausgestellt.<br />
- Anzahl der ausgestellten Lizenzen: $LICENSE_QUANTITY$<br />
- Bestellnummer: $PO_NUMBER$
</p>
<p>
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.
</p>
<p>
Wenn Sie Unterstützung bezüglich ODMS Cloud benötigen, wenden Sie sich
bitte an $DEALER_NAME$.
</p>
<p>
Wenn Sie diese E-Mail fälschlicherweise erhalten haben, löschen Sie
diese E-Mail bitte aus Ihrem System.<br />
Dies ist eine automatisch generierte E-Mail und dieses Postfach wird
nicht überwacht. Bitte nicht antworten.
</p>
</div>
<div>
<h3>&lt;Français&gt;</h3>
<p>Chère/Cher $CUSTOMER_NAME$,</p>
<p>
Les licences ODMS Cloud que vous avez commandées ont été émises.<br />
- Nombre de licences délivrées: $LICENSE_QUANTITY$<br />
- Numéro de bon de commande: $PO_NUMBER$
</p>
<p>
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é.
</p>
<p>
Si vous avez besoin d'assistance concernant ODMS Cloud, veuillez
contacter $DEALER_NAME$.
</p>
<p>
Si vous avez reçu cet e-mail par erreur, veuillez supprimer cet e-mail
de votre système.<br />
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.
</p>
</div>
</body>
</html>

View File

@ -0,0 +1,44 @@
<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.