Merged PR 643: ライセンス引き戻し完了通知 [U-109] の実装
## 概要 [Task3306: ライセンス引き戻し完了通知 [U-109] の実装](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/3306) - ライセンス引き戻し完了のメール送信機能を追加しました。 - テストでメール送信しないようSendGridのメソッドを上書きする処理を追加しました。 ## レビューポイント - テンプレートの適用内容に不自然な点はないか - アカウントのFromとToとCCに関わる部分で認識違いはないか - `orderedAccountId` という引数には注文したアカウント=下位階層のアカウントが入るという理解であっているか等 ## UIの変更 - なし ## 動作確認状況 - npm run testは通過
This commit is contained in:
parent
60bb8f9e20
commit
1bc6618a6d
4
dictation_client/.vscode/settings.json
vendored
4
dictation_client/.vscode/settings.json
vendored
@ -27,8 +27,8 @@
|
||||
"debug.javascript.usePreview": false,
|
||||
"editor.copyWithSyntaxHighlighting": false,
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": true,
|
||||
"source.fixAll.stylelint": true
|
||||
"source.fixAll.eslint": "explicit",
|
||||
"source.fixAll.stylelint": "explicit"
|
||||
},
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.formatOnSave": true,
|
||||
|
||||
2
dictation_server/.vscode/settings.json
vendored
2
dictation_server/.vscode/settings.json
vendored
@ -1,7 +1,7 @@
|
||||
{
|
||||
"terminal.integrated.shell.linux": "/bin/bash",
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": true
|
||||
"source.fixAll.eslint": "explicit"
|
||||
},
|
||||
"eslint.format.enable": false,
|
||||
"[javascript]": {
|
||||
|
||||
@ -5112,6 +5112,7 @@ describe('ライセンス発行キャンセル', () => {
|
||||
);
|
||||
|
||||
const service = module.get<AccountsService>(AccountsService);
|
||||
overrideSendgridService(service, {});
|
||||
await service.cancelIssue(
|
||||
makeContext('trackingId', 'requestId'),
|
||||
tier1Accounts[0].users[0].external_id,
|
||||
@ -5175,6 +5176,7 @@ describe('ライセンス発行キャンセル', () => {
|
||||
);
|
||||
|
||||
const service = module.get<AccountsService>(AccountsService);
|
||||
overrideSendgridService(service, {});
|
||||
await service.cancelIssue(
|
||||
makeContext('trackingId', 'requestId'),
|
||||
tier2Accounts[0].users[0].external_id,
|
||||
@ -5212,6 +5214,7 @@ describe('ライセンス発行キャンセル', () => {
|
||||
});
|
||||
const poNumber = 'CANCEL_TEST';
|
||||
const service = module.get<AccountsService>(AccountsService);
|
||||
overrideSendgridService(service, {});
|
||||
await expect(
|
||||
service.cancelIssue(
|
||||
makeContext('trackingId', 'requestId'),
|
||||
@ -5258,6 +5261,7 @@ describe('ライセンス発行キャンセル', () => {
|
||||
null,
|
||||
);
|
||||
const service = module.get<AccountsService>(AccountsService);
|
||||
overrideSendgridService(service, {});
|
||||
await expect(
|
||||
service.cancelIssue(
|
||||
makeContext('trackingId', 'requestId'),
|
||||
@ -5304,6 +5308,7 @@ describe('ライセンス発行キャンセル', () => {
|
||||
null,
|
||||
);
|
||||
const service = module.get<AccountsService>(AccountsService);
|
||||
overrideSendgridService(service, {});
|
||||
await expect(
|
||||
service.cancelIssue(
|
||||
makeContext('trackingId', 'requestId'),
|
||||
@ -5351,6 +5356,7 @@ describe('ライセンス発行キャンセル', () => {
|
||||
null,
|
||||
);
|
||||
const service = module.get<AccountsService>(AccountsService);
|
||||
overrideSendgridService(service, {});
|
||||
await expect(
|
||||
service.cancelIssue(
|
||||
makeContext('trackingId', 'requestId'),
|
||||
|
||||
@ -1419,11 +1419,42 @@ export class AccountsService {
|
||||
|
||||
try {
|
||||
// 発行キャンセル処理
|
||||
await this.accountRepository.cancelIssue(
|
||||
context,
|
||||
orderedAccountId,
|
||||
poNumber,
|
||||
);
|
||||
const { canceledIssueLicenseOrderId } =
|
||||
await this.accountRepository.cancelIssue(
|
||||
context,
|
||||
orderedAccountId,
|
||||
poNumber,
|
||||
);
|
||||
try {
|
||||
// 発行キャンセルされ、発行済状態から注文中状態に戻った注文を取得する
|
||||
const order = await this.licensesRepository.getLicenseOrder(
|
||||
context,
|
||||
orderedAccountId,
|
||||
poNumber,
|
||||
canceledIssueLicenseOrderId,
|
||||
);
|
||||
if (order == null) {
|
||||
throw new Error('order not found.');
|
||||
}
|
||||
const { quantity, from_account_id, to_account_id } = order;
|
||||
const customer = await this.getAccountInformation(
|
||||
context,
|
||||
from_account_id,
|
||||
);
|
||||
const dealer = await this.getAccountInformation(context, to_account_id);
|
||||
await this.sendgridService.sendMailWithU109(
|
||||
context,
|
||||
dealer.adminEmails,
|
||||
dealer.companyName,
|
||||
quantity,
|
||||
poNumber,
|
||||
customer.adminEmails,
|
||||
customer.companyName,
|
||||
);
|
||||
} catch (e) {
|
||||
this.logger.error(`[${context.getTrackingId()}] error=${e}`);
|
||||
// メール送信の例外はログだけ出して握りつぶす
|
||||
}
|
||||
} catch (e) {
|
||||
this.logger.error(`[${context.getTrackingId()}] error=${e}`);
|
||||
switch (e.constructor) {
|
||||
@ -2326,7 +2357,7 @@ export class AccountsService {
|
||||
const adminEmails = usersInfo.map((x) => {
|
||||
const { emailAddress } = getUserNameAndMailAddress(x);
|
||||
if (emailAddress == null) {
|
||||
throw new Error('dealer admin email-address is not found');
|
||||
throw new Error(`admin email-address is not found. id=${x.id}`);
|
||||
}
|
||||
return emailAddress;
|
||||
});
|
||||
|
||||
@ -34,6 +34,8 @@ export class SendGridService {
|
||||
private readonly templateU107Text: string;
|
||||
private readonly templateU108Html: string;
|
||||
private readonly templateU108Text: string;
|
||||
private readonly templateU109Html: string;
|
||||
private readonly templateU109Text: string;
|
||||
|
||||
constructor(private readonly configService: ConfigService) {
|
||||
this.appDomain = this.configService.getOrThrow<string>('APP_DOMAIN');
|
||||
@ -99,6 +101,15 @@ export class SendGridService {
|
||||
path.resolve(__dirname, `../../templates/template_U_108.txt`),
|
||||
'utf-8',
|
||||
);
|
||||
|
||||
this.templateU109Html = readFileSync(
|
||||
path.resolve(__dirname, `../../templates/template_U_109.html`),
|
||||
'utf-8',
|
||||
);
|
||||
this.templateU109Text = readFileSync(
|
||||
path.resolve(__dirname, `../../templates/template_U_109.txt`),
|
||||
'utf-8',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -408,6 +419,61 @@ export class SendGridService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* U-109のテンプレートを使用したメールを送信する
|
||||
* @param context context
|
||||
* @param dealerEmails ライセンス発行をキャンセルした上位アカウントの管理者(primary/secondary)のメールアドレス
|
||||
* @param dealerAccountName ライセンス発行をキャンセルした上位アカウントの会社名
|
||||
* @param lisenceCount ライセンス発行をキャンセルした対象の注文の内容(ライセンス数)
|
||||
* @param poNumber ライセンス発行をキャンセルした対象の注文の内容(PO番号)
|
||||
* @param customerMails ライセンス発行をキャンセルされたアカウントの管理者(primary/secondary)のメールアドレス
|
||||
* @param customerAccountName ライセンス発行をキャンセルされたアカウントの会社名
|
||||
* @returns
|
||||
*/
|
||||
async sendMailWithU109(
|
||||
context: Context,
|
||||
dealerEmails: string[],
|
||||
dealerAccountName: string,
|
||||
lisenceCount: number,
|
||||
poNumber: string,
|
||||
customerMails: string[],
|
||||
customerAccountName: string,
|
||||
): Promise<void> {
|
||||
this.logger.log(
|
||||
`[IN] [${context.getTrackingId()}] ${this.sendMailWithU109.name}`,
|
||||
);
|
||||
try {
|
||||
const subject = 'License Returned Notification [U-109]';
|
||||
|
||||
// メールの本文を作成する
|
||||
const html = this.templateU109Html
|
||||
.replaceAll(CUSTOMER_NAME, customerAccountName)
|
||||
.replaceAll(DEALER_NAME, dealerAccountName)
|
||||
.replaceAll(PO_NUMBER, poNumber)
|
||||
.replaceAll(LICENSE_QUANTITY, `${lisenceCount}`);
|
||||
const text = this.templateU109Text
|
||||
.replaceAll(CUSTOMER_NAME, customerAccountName)
|
||||
.replaceAll(DEALER_NAME, dealerAccountName)
|
||||
.replaceAll(PO_NUMBER, poNumber)
|
||||
.replaceAll(LICENSE_QUANTITY, `${lisenceCount}`);
|
||||
|
||||
// メールを送信する
|
||||
this.sendMail(
|
||||
context,
|
||||
dealerEmails,
|
||||
customerMails,
|
||||
this.mailFrom,
|
||||
subject,
|
||||
text,
|
||||
html,
|
||||
);
|
||||
} finally {
|
||||
this.logger.log(
|
||||
`[OUT] [${context.getTrackingId()}] ${this.sendMailWithU109.name}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* U-108のテンプレートを使用したメールを送信する
|
||||
* @param context
|
||||
|
||||
@ -774,13 +774,14 @@ export class AccountsRepositoryService {
|
||||
* 注文元アカウントIDとPOナンバーに紐づくライセンス発行をキャンセルする
|
||||
* @param orderedAccountId:キャンセルしたい発行の注文元アカウントID
|
||||
* @param poNumber:POナンバー
|
||||
* @returns { canceledIssueLicenseOrderId } : キャンセルされたライセンス発行に紐づく注文ID
|
||||
*/
|
||||
async cancelIssue(
|
||||
context: Context,
|
||||
orderedAccountId: number,
|
||||
poNumber: string,
|
||||
): Promise<void> {
|
||||
await this.dataSource.transaction(async (entityManager) => {
|
||||
): Promise<{ canceledIssueLicenseOrderId: number }> {
|
||||
return await this.dataSource.transaction(async (entityManager) => {
|
||||
const orderRepo = entityManager.getRepository(LicenseOrder);
|
||||
|
||||
// キャンセル対象の発行を取得
|
||||
@ -862,6 +863,8 @@ export class AccountsRepositoryService {
|
||||
this.isCommentOut,
|
||||
context,
|
||||
);
|
||||
|
||||
return { canceledIssueLicenseOrderId: targetOrder.id };
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
52
dictation_server/src/templates/template_U_109.html
Normal file
52
dictation_server/src/templates/template_U_109.html
Normal file
@ -0,0 +1,52 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>License Returned Notification [U-109]</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div>
|
||||
<h3><English></h3>
|
||||
<p>Dear $DEALER_NAME$,</p>
|
||||
<p>
|
||||
Please be informed that the licenses issued with the following contents has been returned from your customer and placed back into your License inventory.<br />
|
||||
- Company Name: $CUSTOMER_NAME$<br />
|
||||
- Number of canceled licenses: $LICENSE_QUANTITY$<br />
|
||||
- PO Number: $PO_NUMBER$
|
||||
</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><Deutsch></h3>
|
||||
<p>Sehr geehrte(r) $DEALER_NAME$,</p>
|
||||
<p>
|
||||
Bitte beachten Sie, dass die ausgestellten Lizenzen mit den folgenden Inhalten von Ihrem Kunden zurückgegeben und wieder in Ihren Lizenzbestand aufgenommen wurden.<br />
|
||||
- Name der Firma: $CUSTOMER_NAME$<br />
|
||||
- Anzahl der gekündigten Lizenzen: $LICENSE_QUANTITY$<br />
|
||||
- Bestellnummer: $PO_NUMBER$
|
||||
</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><Français></h3>
|
||||
<p>Chère/Cher $DEALER_NAME$,</p>
|
||||
<p>
|
||||
Veuillez noter que les licences émises avec le contenu suivant ont été retournées par votre client et replacées dans votre inventaire de licences.<br />
|
||||
- Nom de l'entreprise: $CUSTOMER_NAME$<br />
|
||||
- Nombre de licences annulées: $LICENSE_QUANTITY$<br />
|
||||
- Numéro de bon de commande $PO_NUMBER$
|
||||
</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>
|
||||
35
dictation_server/src/templates/template_U_109.txt
Normal file
35
dictation_server/src/templates/template_U_109.txt
Normal file
@ -0,0 +1,35 @@
|
||||
<English>
|
||||
|
||||
Dear $DEALER_NAME$,
|
||||
|
||||
Please be informed that the licenses issued with the following contents has been returned from your customer and placed back into your License inventory.
|
||||
- Company Name: $CUSTOMER_NAME$
|
||||
- Number of canceled licenses: $LICENSE_QUANTITY$
|
||||
- PO Number: $PO_NUMBER$
|
||||
|
||||
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) $DEALER_NAME$,
|
||||
|
||||
Bitte beachten Sie, dass die ausgestellten Lizenzen mit den folgenden Inhalten von Ihrem Kunden zurückgegeben und wieder in Ihren Lizenzbestand aufgenommen wurden.
|
||||
- Name der Firma: $CUSTOMER_NAME$
|
||||
- Anzahl der gekündigten Lizenzen: $LICENSE_QUANTITY$
|
||||
- Bestellnummer: $PO_NUMBER$
|
||||
|
||||
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 $DEALER_NAME$,
|
||||
|
||||
Veuillez noter que les licences émises avec le contenu suivant ont été retournées par votre client et replacées dans votre inventaire de licences.
|
||||
- Nom de l'entreprise: $CUSTOMER_NAME$
|
||||
- Nombre de licences annulées: $LICENSE_QUANTITY$
|
||||
- Numéro de bon de commande $PO_NUMBER$
|
||||
|
||||
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.
|
||||
Loading…
x
Reference in New Issue
Block a user