Merged PR 883: Functions修正
## 概要 [Task4132: Functions修正](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/4132) - 自動割り当てを行うライセンスの取得条件を変更 - 有効期限が近いライセンスまたは有効期限が設定されていないライセンス(新規ライセンス)を取得する - 有効期限が近いものから割り当てを行うので、ソートはサーバー側で行うようにした - メール送信処理を追加 ## レビューポイント - テンプレート取得からメール送信までの実装で漏れはないか - テストケースは足りているか ## UIの変更 - Before/Afterのスクショなど - スクショ置き場 ## クエリの変更 - 2行目で割り当てるライセンスを取得しているが、その条件を修正した - https://ndstokyo.sharepoint.com/:u:/r/sites/Piranha/Shared%20Documents/General/OMDS/%E3%82%AF%E3%82%A8%E3%83%AA/task4132/after.log?csf=1&web=1&e=jh49c3 ## 動作確認状況 - ローカルで確認、develop環境で確認など - 行った修正がデグレを発生させていないことを確認できるか - 追加したメール送信処理を確認するように各テストを修正し、テストが通っている - テストの観点を拡充したうえでテストが通っていることを確認 - ライセンス割り当て履歴の内容をより詳細に確認するようにした ## 補足 - 相談、参考資料などがあれば
This commit is contained in:
parent
ba7196cac1
commit
af0ba78ae9
@ -293,3 +293,13 @@ export const HTTP_STATUS_CODES = {
|
||||
BAD_REQUEST: 400,
|
||||
INTERNAL_SERVER_ERROR: 500,
|
||||
};
|
||||
|
||||
/**
|
||||
* メールの置換文字列
|
||||
* @const {string}
|
||||
*/
|
||||
export const CUSTOMER_NAME = "$CUSTOMER_NAME$";
|
||||
export const DEALER_NAME = "$DEALER_NAME$";
|
||||
export const TOP_URL = "$TOP_URL$";
|
||||
export const USER_NAME = "$USER_NAME$";
|
||||
export const USER_EMAIL = "$USER_EMAIL$";
|
||||
@ -404,7 +404,9 @@ async function sendAlertMail(
|
||||
// メールを送信
|
||||
try {
|
||||
await sendgrid.sendMail(
|
||||
targetAccount.primaryAdminEmail,
|
||||
context,
|
||||
[targetAccount.primaryAdminEmail],
|
||||
[],
|
||||
mailFrom,
|
||||
subject,
|
||||
text,
|
||||
@ -464,7 +466,9 @@ async function sendAlertMail(
|
||||
// メールを送信
|
||||
try {
|
||||
await sendgrid.sendMail(
|
||||
targetAccount.secondaryAdminEmail,
|
||||
context,
|
||||
[targetAccount.secondaryAdminEmail],
|
||||
[],
|
||||
mailFrom,
|
||||
subject,
|
||||
text,
|
||||
@ -523,7 +527,9 @@ async function sendAlertMail(
|
||||
// メールを送信
|
||||
try {
|
||||
await sendgrid.sendMail(
|
||||
targetAccount.primaryAdminEmail,
|
||||
context,
|
||||
[targetAccount.primaryAdminEmail],
|
||||
[],
|
||||
mailFrom,
|
||||
subject,
|
||||
text,
|
||||
@ -581,7 +587,9 @@ async function sendAlertMail(
|
||||
// メールを送信
|
||||
try {
|
||||
await sendgrid.sendMail(
|
||||
targetAccount.secondaryAdminEmail,
|
||||
context,
|
||||
[targetAccount.secondaryAdminEmail],
|
||||
[],
|
||||
mailFrom,
|
||||
subject,
|
||||
text,
|
||||
|
||||
@ -1,14 +1,20 @@
|
||||
import { app, InvocationContext, Timer } from "@azure/functions";
|
||||
import { Between, DataSource, In, MoreThan, Repository } from "typeorm";
|
||||
import { Between, DataSource, In, IsNull, MoreThan, Repository } from "typeorm";
|
||||
import { User } from "../entity/user.entity";
|
||||
import { Account } from "../entity/account.entity";
|
||||
import { License, LicenseAllocationHistory } from "../entity/license.entity";
|
||||
import * as dotenv from "dotenv";
|
||||
import {
|
||||
ADB2C_SIGN_IN_TYPE,
|
||||
CUSTOMER_NAME,
|
||||
DEALER_NAME,
|
||||
LICENSE_ALLOCATED_STATUS,
|
||||
LICENSE_TYPE,
|
||||
SWITCH_FROM_TYPE,
|
||||
TIERS,
|
||||
TOP_URL,
|
||||
USER_EMAIL,
|
||||
USER_NAME,
|
||||
USER_ROLES,
|
||||
} from "../constants";
|
||||
import {
|
||||
@ -16,10 +22,19 @@ import {
|
||||
DateWithZeroTime,
|
||||
NewAllocatedLicenseExpirationDate,
|
||||
} from "../common/types/types";
|
||||
import { readFileSync } from "fs";
|
||||
import path from "path";
|
||||
import { SendGridService } from "../sendgrid/sendgrid";
|
||||
import { AdB2cService } from "../adb2c/adb2c";
|
||||
import { RedisClient } from "redis";
|
||||
import { createRedisClient } from "../redis/redis";
|
||||
|
||||
export async function licenseAutoAllocationProcessing(
|
||||
context: InvocationContext,
|
||||
datasource: DataSource,
|
||||
redisClient: RedisClient,
|
||||
sendGrid: SendGridService,
|
||||
adb2c: AdB2cService,
|
||||
dateToTrigger?: Date
|
||||
): Promise<void> {
|
||||
try {
|
||||
@ -32,6 +47,7 @@ export async function licenseAutoAllocationProcessing(
|
||||
currentDateZeroTime = new DateWithZeroTime(dateToTrigger);
|
||||
currentDateEndTime = new DateWithDayEndTime(dateToTrigger);
|
||||
}
|
||||
|
||||
// 自動更新対象の候補となるアカウントを取得
|
||||
const accountRepository = datasource.getRepository(Account);
|
||||
const targetAccounts = await accountRepository.find({
|
||||
@ -55,6 +71,9 @@ export async function licenseAutoAllocationProcessing(
|
||||
await allocateLicense(
|
||||
context,
|
||||
datasource,
|
||||
redisClient,
|
||||
sendGrid,
|
||||
adb2c,
|
||||
autoAllocationList,
|
||||
currentDateZeroTime,
|
||||
currentDateEndTime
|
||||
@ -94,8 +113,25 @@ export async function licenseAutoAllocation(
|
||||
context.error(e);
|
||||
throw e;
|
||||
}
|
||||
let redisClient: RedisClient;
|
||||
try {
|
||||
// redis接続
|
||||
redisClient = createRedisClient();
|
||||
} catch (e) {
|
||||
context.log("redis client create failed.");
|
||||
context.error(e);
|
||||
throw e;
|
||||
}
|
||||
const sendGrid = new SendGridService();
|
||||
const adb2c = new AdB2cService();
|
||||
|
||||
await licenseAutoAllocationProcessing(context, datasource);
|
||||
await licenseAutoAllocationProcessing(
|
||||
context,
|
||||
datasource,
|
||||
redisClient,
|
||||
sendGrid,
|
||||
adb2c
|
||||
);
|
||||
} catch (e) {
|
||||
context.log("licenseAutoAllocation failed.");
|
||||
context.error(e);
|
||||
@ -215,24 +251,45 @@ export async function getAutoAllocatableLicense(
|
||||
try {
|
||||
context.log("[IN]getAutoAllocatableLicense");
|
||||
// 割り当て可能なライセンスを取得
|
||||
const license = await licenseRepository.findOne({
|
||||
where: {
|
||||
account_id: accountId,
|
||||
status: In([
|
||||
LICENSE_ALLOCATED_STATUS.REUSABLE,
|
||||
LICENSE_ALLOCATED_STATUS.UNALLOCATED,
|
||||
]),
|
||||
expiry_date: MoreThan(currentDateEndTime) || null,
|
||||
},
|
||||
order: {
|
||||
expiry_date: "ASC",
|
||||
},
|
||||
const license = await licenseRepository.find({
|
||||
where: [
|
||||
{
|
||||
account_id: accountId,
|
||||
status: In([
|
||||
LICENSE_ALLOCATED_STATUS.REUSABLE,
|
||||
LICENSE_ALLOCATED_STATUS.UNALLOCATED,
|
||||
]),
|
||||
expiry_date: MoreThan(currentDateEndTime),
|
||||
},
|
||||
{
|
||||
account_id: accountId,
|
||||
status: In([
|
||||
LICENSE_ALLOCATED_STATUS.REUSABLE,
|
||||
LICENSE_ALLOCATED_STATUS.UNALLOCATED,
|
||||
]),
|
||||
expiry_date: IsNull(),
|
||||
},
|
||||
],
|
||||
});
|
||||
if (!license) {
|
||||
if (license.length === 0) {
|
||||
// 割り当て可能なライセンスが存在しない場合でもエラーとはしたくないので、undifinedを返却する
|
||||
return undefined;
|
||||
}
|
||||
return license;
|
||||
// ライセンスをソートする
|
||||
// 有効期限が近いものから割り当てるため、expiry_dateがnullのものは最後にする
|
||||
const sortedLicense = license.sort((a, b) => {
|
||||
if (a.expiry_date && b.expiry_date) {
|
||||
return a.expiry_date.getTime() - b.expiry_date.getTime();
|
||||
} else if (a.expiry_date && !b.expiry_date) {
|
||||
return -1;
|
||||
} else if (!a.expiry_date && b.expiry_date) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
// 有効期限が近いライセンスを返却する
|
||||
return sortedLicense[0];
|
||||
} catch (e) {
|
||||
context.error(e);
|
||||
context.log("getAutoAllocatableLicense failed.");
|
||||
@ -253,17 +310,23 @@ export async function getAutoAllocatableLicense(
|
||||
export async function allocateLicense(
|
||||
context: InvocationContext,
|
||||
datasource: DataSource,
|
||||
redisClient: RedisClient,
|
||||
sendGrid: SendGridService,
|
||||
adb2c: AdB2cService,
|
||||
autoAllocationList: autoAllocationList,
|
||||
currentDateZeroTime: DateWithZeroTime,
|
||||
currentDateEndTime: DateWithDayEndTime
|
||||
): Promise<void> {
|
||||
context.log("[IN]allocateLicense");
|
||||
try {
|
||||
context.log("[IN]allocateLicense");
|
||||
|
||||
// 自動更新対象ユーザーにライセンスを割り当てる
|
||||
// 割り当て可能なライセンスが存在するかどうかのフラグ
|
||||
let hasAllocatebleLicense = true;
|
||||
// ユーザーに割り当てられているライセンスが自動更新対象であるかどうかのフラグ
|
||||
let hasAutoRenewLicense = true;
|
||||
for (const userId of autoAllocationList.userIds) {
|
||||
await datasource.transaction(async (entityManager) => {
|
||||
// フラグの初期化
|
||||
hasAutoRenewLicense = true;
|
||||
const licenseRepository = entityManager.getRepository(License);
|
||||
const licenseAllocationHistoryRepo = entityManager.getRepository(
|
||||
LicenseAllocationHistory
|
||||
@ -292,6 +355,7 @@ export async function allocateLicense(
|
||||
});
|
||||
if (!allocatedLicense) {
|
||||
context.log(`skip auto allocation. userID:${userId}`);
|
||||
hasAutoRenewLicense = false;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -365,17 +429,276 @@ export async function allocateLicense(
|
||||
if (!hasAllocatebleLicense) {
|
||||
break;
|
||||
}
|
||||
|
||||
// ユーザーに割り当てられているライセンスが自動更新対象であるかどうかのフラグがfalseの場合、次のユーザーへ
|
||||
if (!hasAutoRenewLicense) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
//メール送信に必要な情報をDBから取得
|
||||
const userRepository = datasource.getRepository(User);
|
||||
const accountRepository = datasource.getRepository(Account);
|
||||
|
||||
// ライセンスを割り当てたユーザーとアカウントの情報を取得
|
||||
const user = await userRepository.findOne({
|
||||
where: { id: userId },
|
||||
});
|
||||
if (!user) {
|
||||
throw new Error(`Target user not found. ${userId}`);
|
||||
}
|
||||
const account = await accountRepository.findOne({
|
||||
where: { id: autoAllocationList.accountId },
|
||||
relations: {
|
||||
primaryAdminUser: true,
|
||||
secondaryAdminUser: true,
|
||||
},
|
||||
});
|
||||
if (!account) {
|
||||
throw new Error(
|
||||
`Target account not found. ${autoAllocationList.accountId}`
|
||||
);
|
||||
}
|
||||
// アカウントのプライマリー管理者が存在しない場合はエラー
|
||||
if (!account.primaryAdminUser) {
|
||||
throw new Error(
|
||||
`Primary admin user not found. accountID: ${account.id}`
|
||||
);
|
||||
}
|
||||
// 親アカウントが存在する場合は取得
|
||||
let parentAccount: Account | null = null;
|
||||
if (account.parent_account_id) {
|
||||
parentAccount = await accountRepository.findOne({
|
||||
where: { id: account.parent_account_id },
|
||||
});
|
||||
if (!parentAccount) {
|
||||
throw new Error(
|
||||
`Parent account not found. accountID: ${account.parent_account_id}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// アカウントの管理者とライセンスを割り当てたユーザーのメールアドレス取得に必要な外部IDを抽出
|
||||
const externalIds: string[] = [];
|
||||
externalIds.push(user.external_id);
|
||||
externalIds.push(account.primaryAdminUser.external_id);
|
||||
// セカンダリ管理者が存在する場合はセカンダリ管理者の外部IDも抽出
|
||||
if (account.secondaryAdminUser) {
|
||||
externalIds.push(account.secondaryAdminUser.external_id);
|
||||
}
|
||||
const adb2cUsers = await getMailAddressAndDisplayNameList(
|
||||
context,
|
||||
redisClient,
|
||||
adb2c,
|
||||
externalIds
|
||||
);
|
||||
// ライセンス割り当てされたユーザーの名前を取得
|
||||
const userName = adb2cUsers.find(
|
||||
(adb2cUser) => adb2cUser.externalId === user.external_id
|
||||
)?.displayName;
|
||||
if (!userName) {
|
||||
throw new Error(
|
||||
`Target ADb2Cuser name not found. externalId=${user.external_id}`
|
||||
);
|
||||
}
|
||||
// ライセンス割り当てされたユーザーのメールアドレスを取得
|
||||
const userMail = adb2cUsers.find(
|
||||
(adb2cUser) => adb2cUser.externalId === user.external_id
|
||||
)?.mailAddress;
|
||||
if (!userMail) {
|
||||
throw new Error(
|
||||
`Target ADb2Cuser mail not found. externalId=${user.external_id}`
|
||||
);
|
||||
}
|
||||
// アカウントのプライマリー管理者のメールアドレスを取得
|
||||
const adminMails: string[] = [];
|
||||
const primaryAdminMail = adb2cUsers.find(
|
||||
(adb2cUser) =>
|
||||
adb2cUser.externalId === account.primaryAdminUser?.external_id
|
||||
)?.mailAddress;
|
||||
if (!primaryAdminMail) {
|
||||
throw new Error(
|
||||
`Primary admin user mail not found. externalId=${account.primaryAdminUser.external_id}`
|
||||
);
|
||||
}
|
||||
adminMails.push(primaryAdminMail);
|
||||
|
||||
// アカウントのセカンダリ管理者のメールアドレスを取得
|
||||
const secondaryAdminMail = adb2cUsers.find(
|
||||
(adb2cUser) =>
|
||||
adb2cUser.externalId === account.secondaryAdminUser?.external_id
|
||||
)?.mailAddress;
|
||||
if (secondaryAdminMail) {
|
||||
adminMails.push(secondaryAdminMail);
|
||||
}
|
||||
|
||||
// メール送信
|
||||
await sendMailWithU108(
|
||||
context,
|
||||
userName,
|
||||
userMail,
|
||||
adminMails,
|
||||
account.company_name,
|
||||
parentAccount ? parentAccount.company_name : null,
|
||||
sendGrid
|
||||
);
|
||||
} catch (e) {
|
||||
context.error(`error=${e}`);
|
||||
// メール送信に関する例外はログだけ出して握りつぶす
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
// エラーが発生しても次のアカウントへの処理は継続させるため、例外をthrowせずにreturnだけする
|
||||
context.error(e);
|
||||
context.log("allocateLicense failed.");
|
||||
context.error(e);
|
||||
return;
|
||||
} finally {
|
||||
context.log("[OUT]allocateLicense");
|
||||
}
|
||||
}
|
||||
|
||||
// adb2cから指定した外部IDのユーザー情報を取得する
|
||||
export async function getMailAddressAndDisplayNameList(
|
||||
context: InvocationContext,
|
||||
redisClient: RedisClient,
|
||||
adb2c: AdB2cService,
|
||||
externalIds: string[]
|
||||
): Promise<
|
||||
{
|
||||
externalId: string;
|
||||
displayName: string;
|
||||
mailAddress: string;
|
||||
}[]
|
||||
> {
|
||||
context.log("[IN]getUsers");
|
||||
try {
|
||||
const users = [] as {
|
||||
externalId: string;
|
||||
displayName: string;
|
||||
mailAddress: string;
|
||||
}[];
|
||||
// 外部IDからADB2Cユーザー情報を取得
|
||||
const adb2cUsers = await adb2c.getUsers(context, redisClient, externalIds);
|
||||
for (const externalId of externalIds) {
|
||||
const adb2cUser = adb2cUsers.find((user) => user.id === externalId);
|
||||
if (!adb2cUser) {
|
||||
throw new Error(`ADB2C user not found. externalId=${externalId}`);
|
||||
}
|
||||
const mailAddress = adb2cUser.identities?.find(
|
||||
(identity) => identity.signInType === ADB2C_SIGN_IN_TYPE.EMAILADDRESS
|
||||
)?.issuerAssignedId;
|
||||
if (!mailAddress) {
|
||||
throw new Error(`ADB2C user mail not found. externalId=${externalId}`);
|
||||
}
|
||||
users.push({
|
||||
externalId: externalId,
|
||||
displayName: adb2cUser.displayName,
|
||||
mailAddress: mailAddress,
|
||||
});
|
||||
}
|
||||
return users;
|
||||
} catch (e) {
|
||||
context.error(e);
|
||||
context.log("getUsers failed.");
|
||||
throw e;
|
||||
} finally {
|
||||
context.log("[OUT]getUsers");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* U-108のテンプレートを使用したメールを送信する
|
||||
* @param context
|
||||
* @param userName ライセンス割り当てされたユーザーの名前
|
||||
* @param userMail ライセンス割り当てされたユーザーのメールアドレス
|
||||
* @param customerAdminMails ライセンス割り当てされたユーザーの所属するアカウントの管理者(primary/secondary)のメールアドレス
|
||||
* @param customerAccountName ライセンス割り当てされたユーザーの所属するアカウントの名前
|
||||
* @param dealerAccountName 問題発生時に問い合わせする先の上位のディーラー名(会社名)
|
||||
* @returns mail with u108
|
||||
*/
|
||||
export async function sendMailWithU108(
|
||||
context: InvocationContext,
|
||||
userName: string,
|
||||
userMail: string,
|
||||
customerAdminMails: string[],
|
||||
customerAccountName: string,
|
||||
dealerAccountName: string | null,
|
||||
sendGrid: SendGridService
|
||||
): Promise<void> {
|
||||
context.log("[IN] sendMailWithU108");
|
||||
try {
|
||||
const subject = "License Assigned Notification [U-108]";
|
||||
const domain = process.env.APP_DOMAIN;
|
||||
if (!domain) {
|
||||
throw new Error("APP_DOMAIN is not defined.");
|
||||
}
|
||||
const mailFrom = process.env.MAIL_FROM;
|
||||
if (!mailFrom) {
|
||||
throw new Error("MAIL_FROM is not defined.");
|
||||
}
|
||||
const url = new URL(domain).href;
|
||||
|
||||
let html: string;
|
||||
let text: string;
|
||||
|
||||
if (dealerAccountName === null) {
|
||||
const templateU108NoParentHtml = readFileSync(
|
||||
path.resolve(__dirname, `../templates/template_U_108_no_parent.html`),
|
||||
"utf-8"
|
||||
);
|
||||
const templateU108NoParentText = readFileSync(
|
||||
path.resolve(__dirname, `../templates/template_U_108_no_parent.txt`),
|
||||
"utf-8"
|
||||
);
|
||||
html = templateU108NoParentHtml
|
||||
.replaceAll(CUSTOMER_NAME, customerAccountName)
|
||||
.replaceAll(USER_NAME, userName)
|
||||
.replaceAll(USER_EMAIL, userMail)
|
||||
.replaceAll(TOP_URL, url);
|
||||
text = templateU108NoParentText
|
||||
.replaceAll(CUSTOMER_NAME, customerAccountName)
|
||||
.replaceAll(USER_NAME, userName)
|
||||
.replaceAll(USER_EMAIL, userMail)
|
||||
.replaceAll(TOP_URL, url);
|
||||
} else {
|
||||
const templateU108Html = readFileSync(
|
||||
path.resolve(__dirname, `../templates/template_U_108.html`),
|
||||
"utf-8"
|
||||
);
|
||||
const templateU108Text = readFileSync(
|
||||
path.resolve(__dirname, `../templates/template_U_108.txt`),
|
||||
"utf-8"
|
||||
);
|
||||
html = templateU108Html
|
||||
.replaceAll(CUSTOMER_NAME, customerAccountName)
|
||||
.replaceAll(DEALER_NAME, dealerAccountName)
|
||||
.replaceAll(USER_NAME, userName)
|
||||
.replaceAll(USER_EMAIL, userMail)
|
||||
.replaceAll(TOP_URL, url);
|
||||
text = templateU108Text
|
||||
.replaceAll(CUSTOMER_NAME, customerAccountName)
|
||||
.replaceAll(DEALER_NAME, dealerAccountName)
|
||||
.replaceAll(USER_NAME, userName)
|
||||
.replaceAll(USER_EMAIL, userMail)
|
||||
.replaceAll(TOP_URL, url);
|
||||
}
|
||||
const ccAddress = customerAdminMails.includes(userMail) ? [] : [userMail];
|
||||
|
||||
// メールを送信する
|
||||
await sendGrid.sendMail(
|
||||
context,
|
||||
customerAdminMails,
|
||||
ccAddress,
|
||||
mailFrom,
|
||||
subject,
|
||||
text,
|
||||
html
|
||||
);
|
||||
} finally {
|
||||
context.log(`[OUT] sendMailWithU108`);
|
||||
}
|
||||
}
|
||||
|
||||
app.timer("licenseAutoAllocation", {
|
||||
schedule: "0 0 16 * * *",
|
||||
handler: licenseAutoAllocation,
|
||||
|
||||
@ -12,6 +12,10 @@ import { User } from "../entity/user.entity";
|
||||
import { Account } from "../entity/account.entity";
|
||||
import { License, LicenseAllocationHistory } from "../entity/license.entity";
|
||||
import { HTTP_METHODS, HTTP_STATUS_CODES } from "../constants";
|
||||
import { RedisClient } from "redis";
|
||||
import { createRedisClient } from "../redis/redis";
|
||||
import { AdB2cService } from "../adb2c/adb2c";
|
||||
import { SendGridService } from "../sendgrid/sendgrid";
|
||||
|
||||
export async function licenseAutoAllocationManualRetry(
|
||||
req: HttpRequest,
|
||||
@ -57,8 +61,27 @@ export async function licenseAutoAllocationManualRetry(
|
||||
context.error(e);
|
||||
throw e;
|
||||
}
|
||||
let redisClient: RedisClient;
|
||||
try {
|
||||
// redis接続
|
||||
redisClient = createRedisClient();
|
||||
} catch (e) {
|
||||
context.log("redis client create failed.");
|
||||
context.error(e);
|
||||
throw e;
|
||||
}
|
||||
const sendGrid = new SendGridService();
|
||||
const adb2c = new AdB2cService();
|
||||
|
||||
await licenseAutoAllocationProcessing(context, datasource, dateToTrigger);
|
||||
|
||||
await licenseAutoAllocationProcessing(
|
||||
context,
|
||||
datasource,
|
||||
redisClient,
|
||||
sendGrid,
|
||||
adb2c,
|
||||
dateToTrigger
|
||||
);
|
||||
context.log("Automatic license allocation has been triggered.");
|
||||
return {
|
||||
status: HTTP_STATUS_CODES.OK,
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { InvocationContext } from "@azure/functions";
|
||||
import sendgrid from "@sendgrid/mail";
|
||||
import { error } from "console";
|
||||
|
||||
@ -9,9 +10,11 @@ export class SendGridService {
|
||||
sendgrid.setApiKey(process.env.SENDGRID_API_KEY);
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* メールを送信する
|
||||
* @param context
|
||||
* @param to
|
||||
* @param cc
|
||||
* @param from
|
||||
* @param subject
|
||||
* @param text
|
||||
@ -19,28 +22,40 @@ export class SendGridService {
|
||||
* @returns mail
|
||||
*/
|
||||
async sendMail(
|
||||
to: string,
|
||||
context: InvocationContext,
|
||||
to: string[],
|
||||
cc: string[],
|
||||
from: string,
|
||||
subject: string,
|
||||
text: string,
|
||||
html: string
|
||||
html: string,
|
||||
): Promise<void> {
|
||||
context.log(`[IN] ${this.sendMail.name}`);
|
||||
try {
|
||||
const res = await sendgrid
|
||||
.send({
|
||||
from: {
|
||||
email: from,
|
||||
},
|
||||
to: {
|
||||
email: to,
|
||||
},
|
||||
to: to.map((v) => ({ email: v })),
|
||||
cc: cc.map((v) => ({ email: v })),
|
||||
subject: subject,
|
||||
text: text,
|
||||
html: html,
|
||||
})
|
||||
.then((v) => v[0]);
|
||||
context.log(
|
||||
` status code: ${
|
||||
res.statusCode
|
||||
} body: ${JSON.stringify(res.body)}`,
|
||||
);
|
||||
} catch (e) {
|
||||
context.warn(`send mail faild.`);
|
||||
context.warn(`${this.sendMail.name} error=${e}`);
|
||||
throw e;
|
||||
} finally {
|
||||
context.log(`[OUT] ${this.sendMail.name}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
81
dictation_function/src/templates/template_U_108.html
Normal file
81
dictation_function/src/templates/template_U_108.html
Normal file
@ -0,0 +1,81 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>License Assigned Notification [U-108]</title>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
<h3><English></h3>
|
||||
<p>Dear $CUSTOMER_NAME$,</p>
|
||||
<p>
|
||||
Please be informed that a license has been assigned to the following
|
||||
user.<br />
|
||||
- User Name: $USER_NAME$<br />
|
||||
- Email: $USER_EMAIL$
|
||||
</p>
|
||||
<p>
|
||||
Please log in to ODMS Cloud to verify the license expiration date.<br />
|
||||
URL: $TOP_URL$
|
||||
</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><Deutsch></h3>
|
||||
<p>Sehr geehrte(r) $CUSTOMER_NAME$,</p>
|
||||
<p>
|
||||
Bitte beachten Sie, dass dem folgenden Benutzer eine Lizenz zugewiesen
|
||||
wurde.<br />
|
||||
- Nutzername: $USER_NAME$<br />
|
||||
- Email: $USER_EMAIL$
|
||||
</p>
|
||||
<p>
|
||||
Bitte melden Sie sich bei ODMS Cloud an, um das Ablaufdatum der Lizenz
|
||||
zu überprüfen.<br />
|
||||
URL: $TOP_URL$
|
||||
</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 irrtümlich erhalten haben, löschen Sie diese
|
||||
E-Mail bitte aus Ihrem System.<br />
|
||||
Dies ist eine automatisch generierte
|
||||
E-Mail und diese Mailbox wird nicht überwacht. Bitte antworten Sie
|
||||
nicht.
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<h3><Français></h3>
|
||||
<p>Chère/Cher $CUSTOMER_NAME$,</p>
|
||||
<p>
|
||||
Veuillez être informé qu'une licence a été attribuée à l'utilisateur
|
||||
suivant.<br />
|
||||
- Nom d'utilisateur: $USER_NAME$<br />
|
||||
- Email: $USER_EMAIL$
|
||||
</p>
|
||||
<p>
|
||||
Veuillez vous connecter à ODMS Cloud pour vérifier la date d'expiration
|
||||
de la licence.<br />
|
||||
URL: $TOP_URL$
|
||||
</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>
|
||||
47
dictation_function/src/templates/template_U_108.txt
Normal file
47
dictation_function/src/templates/template_U_108.txt
Normal file
@ -0,0 +1,47 @@
|
||||
<English>
|
||||
|
||||
Dear $CUSTOMER_NAME$,
|
||||
|
||||
Please be informed that a license has been assigned to the following user.
|
||||
- User Name: $USER_NAME$
|
||||
- Email: $USER_EMAIL$
|
||||
|
||||
Please log in to ODMS Cloud to verify the license expiration date.
|
||||
URL: $TOP_URL$
|
||||
|
||||
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$,
|
||||
|
||||
Bitte beachten Sie, dass dem folgenden Benutzer eine Lizenz zugewiesen wurde.
|
||||
- Nutzername: $USER_NAME$
|
||||
- Email: $USER_EMAIL$
|
||||
|
||||
Bitte melden Sie sich bei ODMS Cloud an, um das Ablaufdatum der Lizenz zu überprüfen.
|
||||
URL: $TOP_URL$
|
||||
|
||||
Wenn Sie Unterstützung bezüglich ODMS Cloud benötigen, wenden Sie sich bitte an $DEALER_NAME$.
|
||||
|
||||
Wenn Sie diese E-Mail irrtümlich erhalten haben, löschen Sie diese E-Mail bitte aus Ihrem System.
|
||||
Dies ist eine automatisch generierte E-Mail und diese Mailbox wird nicht überwacht. Bitte antworten Sie nicht.
|
||||
|
||||
<Français>
|
||||
|
||||
Chère/Cher $CUSTOMER_NAME$,
|
||||
|
||||
Veuillez être informé qu'une licence a été attribuée à l'utilisateur suivant.
|
||||
- Nom d'utilisateur: $USER_NAME$
|
||||
- Email: $USER_EMAIL$
|
||||
|
||||
Veuillez vous connecter à ODMS Cloud pour vérifier la date d'expiration de la licence.
|
||||
URL: $TOP_URL$
|
||||
|
||||
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.
|
||||
@ -0,0 +1,70 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>License Assigned Notification [U-108]</title>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
<h3><English></h3>
|
||||
<p>Dear $CUSTOMER_NAME$,</p>
|
||||
<p>
|
||||
Please be informed that a license has been assigned to the following
|
||||
user.<br />
|
||||
- User Name: $USER_NAME$<br />
|
||||
- Email: $USER_EMAIL$
|
||||
</p>
|
||||
<p>
|
||||
Please log in to ODMS Cloud to verify the license expiration date.<br />
|
||||
URL: $TOP_URL$
|
||||
</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) $CUSTOMER_NAME$,</p>
|
||||
<p>
|
||||
Bitte beachten Sie, dass dem folgenden Benutzer eine Lizenz zugewiesen
|
||||
wurde.<br />
|
||||
- Nutzername: $USER_NAME$<br />
|
||||
- Email: $USER_EMAIL$
|
||||
</p>
|
||||
<p>
|
||||
Bitte melden Sie sich bei ODMS Cloud an, um das Ablaufdatum der Lizenz
|
||||
zu überprüfen.<br />
|
||||
URL: $TOP_URL$
|
||||
</p>
|
||||
<p>
|
||||
Wenn Sie diese E-Mail irrtümlich erhalten haben, löschen Sie diese
|
||||
E-Mail bitte aus Ihrem System.<br />
|
||||
Dies ist eine automatisch generierte
|
||||
E-Mail und diese Mailbox wird nicht überwacht. Bitte antworten Sie
|
||||
nicht.
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<h3><Français></h3>
|
||||
<p>Chère/Cher $CUSTOMER_NAME$,</p>
|
||||
<p>
|
||||
Veuillez être informé qu'une licence a été attribuée à l'utilisateur
|
||||
suivant.<br />
|
||||
- Nom d'utilisateur: $USER_NAME$<br />
|
||||
- Email: $USER_EMAIL$
|
||||
</p>
|
||||
<p>
|
||||
Veuillez vous connecter à ODMS Cloud pour vérifier la date d'expiration
|
||||
de la licence.<br />
|
||||
URL: $TOP_URL$
|
||||
</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>
|
||||
@ -0,0 +1,41 @@
|
||||
<English>
|
||||
|
||||
Dear $CUSTOMER_NAME$,
|
||||
|
||||
Please be informed that a license has been assigned to the following user.
|
||||
- User Name: $USER_NAME$
|
||||
- Email: $USER_EMAIL$
|
||||
|
||||
Please log in to ODMS Cloud to verify the license expiration date.
|
||||
URL: $TOP_URL$
|
||||
|
||||
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$,
|
||||
|
||||
Bitte beachten Sie, dass dem folgenden Benutzer eine Lizenz zugewiesen wurde.
|
||||
- Nutzername: $USER_NAME$
|
||||
- Email: $USER_EMAIL$
|
||||
|
||||
Bitte melden Sie sich bei ODMS Cloud an, um das Ablaufdatum der Lizenz zu überprüfen.
|
||||
URL: $TOP_URL$
|
||||
|
||||
Wenn Sie diese E-Mail irrtümlich erhalten haben, löschen Sie diese E-Mail bitte aus Ihrem System.
|
||||
Dies ist eine automatisch generierte E-Mail und diese Mailbox wird nicht überwacht. Bitte antworten Sie nicht.
|
||||
|
||||
<Français>
|
||||
|
||||
Chère/Cher $CUSTOMER_NAME$,
|
||||
|
||||
Veuillez être informé qu'une licence a été attribuée à l'utilisateur suivant.
|
||||
- Nom d'utilisateur: $USER_NAME$
|
||||
- Email: $USER_EMAIL$
|
||||
|
||||
Veuillez vous connecter à ODMS Cloud pour vérifier la date d'expiration de la licence.
|
||||
URL: $TOP_URL$
|
||||
|
||||
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.
|
||||
88
dictation_function/src/test/common/adb2c.mock.ts
Normal file
88
dictation_function/src/test/common/adb2c.mock.ts
Normal file
@ -0,0 +1,88 @@
|
||||
import { InvocationContext } from "@azure/functions";
|
||||
import { AdB2cUser } from "../../adb2c/types/types";
|
||||
import { ADB2C_SIGN_IN_TYPE } from "../../constants";
|
||||
import { RedisClient } from "redis-mock";
|
||||
|
||||
// テスト用adb2c
|
||||
export class AdB2cServiceMock {
|
||||
/**
|
||||
* Azure AD B2Cからユーザ情報を取得する
|
||||
* @param externalIds 外部ユーザーID
|
||||
* @returns ユーザ情報
|
||||
*/
|
||||
async getUsers(
|
||||
context: InvocationContext,
|
||||
redisClient: RedisClient,
|
||||
externalIds: string[]
|
||||
): Promise<AdB2cUser[]> {
|
||||
const AdB2cMockUsers: AdB2cUser[] = [
|
||||
{
|
||||
id: "external_id1",
|
||||
displayName: "test1",
|
||||
identities: [
|
||||
{
|
||||
signInType: ADB2C_SIGN_IN_TYPE.EMAILADDRESS,
|
||||
issuer: "issuer",
|
||||
issuerAssignedId: "test1@mail.com",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "external_id2",
|
||||
displayName: "test2",
|
||||
identities: [
|
||||
{
|
||||
signInType: ADB2C_SIGN_IN_TYPE.EMAILADDRESS,
|
||||
issuer: "issuer",
|
||||
issuerAssignedId: "test2@mail.com",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "external_id3",
|
||||
displayName: "test3",
|
||||
identities: [
|
||||
{
|
||||
signInType: ADB2C_SIGN_IN_TYPE.EMAILADDRESS,
|
||||
issuer: "issuer",
|
||||
issuerAssignedId: "test3@mail.com",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "external_id4",
|
||||
displayName: "test4",
|
||||
identities: [
|
||||
{
|
||||
signInType: ADB2C_SIGN_IN_TYPE.EMAILADDRESS,
|
||||
issuer: "issuer",
|
||||
issuerAssignedId: "test4@mail.com",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "external_id5",
|
||||
displayName: "test5",
|
||||
identities: [
|
||||
{
|
||||
signInType: ADB2C_SIGN_IN_TYPE.EMAILADDRESS,
|
||||
issuer: "issuer",
|
||||
issuerAssignedId: "test5@mail.com",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "external_id6",
|
||||
displayName: "test6",
|
||||
identities: [
|
||||
{
|
||||
signInType: ADB2C_SIGN_IN_TYPE.EMAILADDRESS,
|
||||
issuer: "issuer",
|
||||
issuerAssignedId: "test6@mail.com",
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
return AdB2cMockUsers;
|
||||
}
|
||||
}
|
||||
24
dictation_function/src/test/common/sendGrid.mock.ts
Normal file
24
dictation_function/src/test/common/sendGrid.mock.ts
Normal file
@ -0,0 +1,24 @@
|
||||
import { InvocationContext } from "@azure/functions";
|
||||
|
||||
export class SendGridServiceMock {
|
||||
/**
|
||||
* メールを送信する
|
||||
* @param to
|
||||
* @param from
|
||||
* @param subject
|
||||
* @param text
|
||||
* @param html
|
||||
* @returns mail
|
||||
*/
|
||||
async sendMail(
|
||||
context: InvocationContext,
|
||||
to: string[],
|
||||
cc: string[],
|
||||
from: string,
|
||||
subject: string,
|
||||
text: string,
|
||||
html: string
|
||||
): Promise<void> {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -173,7 +173,7 @@ export const makeTestAccount = async (
|
||||
};
|
||||
};
|
||||
|
||||
export const createLicense = async (
|
||||
export const createAndAllocateLicense = async (
|
||||
datasource: DataSource,
|
||||
licenseId: number,
|
||||
expiry_date: Date | null,
|
||||
@ -201,6 +201,29 @@ export const createLicense = async (
|
||||
updated_at: new Date(),
|
||||
});
|
||||
identifiers.pop() as License;
|
||||
// 割り当てるユーザーがいない場合は履歴を作成しない
|
||||
if (!allocated_user_id) {
|
||||
return;
|
||||
}
|
||||
// switch_from_typeを作成
|
||||
// typeが"CARD"の場合は"CARD","TRIAL"の場合は"TRIAL","NORMAL"の場合は"NONE"を設定
|
||||
|
||||
const switch_from_type =
|
||||
type === "CARD" ? "CARD" : type === "TRIAL" ? "TRIAL" : "NONE";
|
||||
|
||||
// ライセンスの割り当て履歴を作成
|
||||
await datasource.getRepository(LicenseAllocationHistory).insert({
|
||||
license_id: licenseId,
|
||||
account_id: accountId,
|
||||
user_id: allocated_user_id ?? -1,
|
||||
is_allocated: true,
|
||||
switch_from_type: switch_from_type,
|
||||
executed_at: new Date(),
|
||||
created_by: "test_runner",
|
||||
created_at: new Date(),
|
||||
updated_by: "updater",
|
||||
updated_at: new Date(),
|
||||
});
|
||||
};
|
||||
|
||||
export const selectLicenseByAllocatedUser = async (
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { DataSource } from "typeorm";
|
||||
import { licenseAlertProcessing } from "../functions/licenseAlert";
|
||||
import { makeTestAccount, createLicense } from "./common/utility";
|
||||
import { makeTestAccount, createAndAllocateLicense } from "./common/utility";
|
||||
import * as dotenv from "dotenv";
|
||||
import {
|
||||
DateWithDayEndTime,
|
||||
@ -8,13 +8,13 @@ import {
|
||||
ExpirationThresholdDate,
|
||||
NewTrialLicenseExpirationDate,
|
||||
} from "../common/types/types";
|
||||
import { AdB2cUser } from "../adb2c/types/types";
|
||||
import { ADB2C_SIGN_IN_TYPE } from "../constants";
|
||||
import { SendGridService } from "../sendgrid/sendgrid";
|
||||
import { AdB2cService } from "../adb2c/adb2c";
|
||||
import { InvocationContext } from "@azure/functions";
|
||||
import { RedisClient, createClient } from "redis-mock";
|
||||
import { createClient } from "redis-mock";
|
||||
import { promisify } from "util";
|
||||
import { SendGridServiceMock } from "./common/sendGrid.mock";
|
||||
import { AdB2cServiceMock } from "./common/adb2c.mock";
|
||||
|
||||
describe("licenseAlert", () => {
|
||||
dotenv.config({ path: ".env" });
|
||||
@ -56,7 +56,7 @@ describe("licenseAlert", () => {
|
||||
{ tier: 5 },
|
||||
{ external_id: "external_id1", accepted_dpa_version: null }
|
||||
);
|
||||
await createLicense(
|
||||
await createAndAllocateLicense(
|
||||
source,
|
||||
1,
|
||||
expiringSoonDate,
|
||||
@ -103,7 +103,7 @@ describe("licenseAlert", () => {
|
||||
accepted_dpa_version: null,
|
||||
}
|
||||
);
|
||||
await createLicense(
|
||||
await createAndAllocateLicense(
|
||||
source,
|
||||
1,
|
||||
expiringSoonDate,
|
||||
@ -147,7 +147,7 @@ describe("licenseAlert", () => {
|
||||
{ tier: 5 },
|
||||
{ external_id: "external_id3", accepted_dpa_version: null }
|
||||
);
|
||||
await createLicense(
|
||||
await createAndAllocateLicense(
|
||||
source,
|
||||
1,
|
||||
expiringSoonDate,
|
||||
@ -159,7 +159,7 @@ describe("licenseAlert", () => {
|
||||
null,
|
||||
null
|
||||
);
|
||||
await createLicense(
|
||||
await createAndAllocateLicense(
|
||||
source,
|
||||
2,
|
||||
expiryDate,
|
||||
@ -206,7 +206,7 @@ describe("licenseAlert", () => {
|
||||
accepted_dpa_version: null,
|
||||
}
|
||||
);
|
||||
await createLicense(
|
||||
await createAndAllocateLicense(
|
||||
source,
|
||||
1,
|
||||
expiringSoonDate,
|
||||
@ -254,7 +254,7 @@ describe("licenseAlert", () => {
|
||||
accepted_privacy_notice_version: null,
|
||||
}
|
||||
);
|
||||
await createLicense(
|
||||
await createAndAllocateLicense(
|
||||
source,
|
||||
1,
|
||||
expiringSoonDate,
|
||||
@ -278,97 +278,6 @@ describe("licenseAlert", () => {
|
||||
});
|
||||
});
|
||||
|
||||
// テスト用sendgrid
|
||||
export class SendGridServiceMock {
|
||||
/**
|
||||
* メールを送信する
|
||||
* @param to
|
||||
* @param from
|
||||
* @param subject
|
||||
* @param text
|
||||
* @param html
|
||||
* @returns mail
|
||||
*/
|
||||
async sendMail(
|
||||
to: string,
|
||||
from: string,
|
||||
subject: string,
|
||||
text: string,
|
||||
html: string
|
||||
): Promise<void> {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// テスト用adb2c
|
||||
export class AdB2cServiceMock {
|
||||
/**
|
||||
* Azure AD B2Cからユーザ情報を取得する
|
||||
* @param externalIds 外部ユーザーID
|
||||
* @returns ユーザ情報
|
||||
*/
|
||||
async getUsers(
|
||||
context: InvocationContext,
|
||||
redisClient: RedisClient,
|
||||
externalIds: string[]
|
||||
): Promise<AdB2cUser[]> {
|
||||
const AdB2cMockUsers: AdB2cUser[] = [
|
||||
{
|
||||
id: "external_id1",
|
||||
displayName: "test1",
|
||||
identities: [
|
||||
{
|
||||
signInType: ADB2C_SIGN_IN_TYPE.EMAILADDRESS,
|
||||
issuer: "issuer",
|
||||
issuerAssignedId: "test1@mail.com",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "external_id2",
|
||||
displayName: "test2",
|
||||
identities: [
|
||||
{
|
||||
signInType: ADB2C_SIGN_IN_TYPE.EMAILADDRESS,
|
||||
issuer: "issuer",
|
||||
issuerAssignedId: "test2@mail.com",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "external_id3",
|
||||
displayName: "test3",
|
||||
identities: [
|
||||
{
|
||||
signInType: ADB2C_SIGN_IN_TYPE.EMAILADDRESS,
|
||||
issuer: "issuer",
|
||||
issuerAssignedId: "test3@mail.com",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "external_id4",
|
||||
displayName: "test4",
|
||||
identities: [
|
||||
{
|
||||
signInType: ADB2C_SIGN_IN_TYPE.EMAILADDRESS,
|
||||
issuer: "issuer",
|
||||
issuerAssignedId: "test4@mail.com",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "external_id5",
|
||||
displayName: "test5",
|
||||
identities: [
|
||||
{
|
||||
signInType: ADB2C_SIGN_IN_TYPE.EMAILADDRESS,
|
||||
issuer: "issuer",
|
||||
issuerAssignedId: "test5@mail.com",
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
return AdB2cMockUsers;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -8,18 +8,24 @@ import {
|
||||
import { DateWithDayEndTime } from "../common/types/types";
|
||||
import {
|
||||
makeTestAccount,
|
||||
createLicense,
|
||||
createAndAllocateLicense,
|
||||
makeTestUser,
|
||||
selectLicenseByAllocatedUser,
|
||||
selectLicenseAllocationHistory,
|
||||
} from "./common/utility";
|
||||
import * as dotenv from "dotenv";
|
||||
import { InvocationContext } from "@azure/functions";
|
||||
import { AdB2cService } from "../adb2c/adb2c";
|
||||
import { SendGridService } from "../sendgrid/sendgrid";
|
||||
import { SendGridServiceMock } from "./common/sendGrid.mock";
|
||||
import { AdB2cServiceMock } from "./common/adb2c.mock";
|
||||
import { createClient } from "redis-mock";
|
||||
|
||||
describe("licenseAutoAllocation", () => {
|
||||
dotenv.config({ path: ".env" });
|
||||
dotenv.config({ path: ".env.local", override: true });
|
||||
let source: DataSource | null = null;
|
||||
const redisClient = createClient();
|
||||
beforeEach(async () => {
|
||||
source = new DataSource({
|
||||
type: "sqlite",
|
||||
@ -40,33 +46,39 @@ describe("licenseAutoAllocation", () => {
|
||||
it("有効期限が本日のライセンスが自動更新されること", async () => {
|
||||
if (!source) fail();
|
||||
const context = new InvocationContext();
|
||||
|
||||
const sendgridMock = new SendGridServiceMock() as SendGridService;
|
||||
const adb2cMock = new AdB2cServiceMock() as AdB2cService;
|
||||
// 呼び出し回数でテスト成否を判定
|
||||
const spySend = jest.spyOn(sendgridMock, "sendMail");
|
||||
const currentDateEndTime = new DateWithDayEndTime();
|
||||
|
||||
// アカウント
|
||||
const account1 = await makeTestAccount(
|
||||
source,
|
||||
{ tier: 5 },
|
||||
{ role: `${USER_ROLES.NONE}` }
|
||||
{ role: `${USER_ROLES.NONE}`, external_id: "external_id1" }
|
||||
);
|
||||
const account2 = await makeTestAccount(
|
||||
source,
|
||||
{ tier: 5 },
|
||||
{ role: `${USER_ROLES.NONE}` }
|
||||
{ role: `${USER_ROLES.NONE}`, external_id: "external_id6" }
|
||||
);
|
||||
|
||||
// 更新対象のユーザー(3role分)
|
||||
const user1 = await makeTestUser(source, {
|
||||
account_id: account1.account.id,
|
||||
role: `${USER_ROLES.NONE}`,
|
||||
external_id: "external_id2",
|
||||
});
|
||||
const user2 = await makeTestUser(source, {
|
||||
account_id: account1.account.id,
|
||||
role: `${USER_ROLES.AUTHOR}`,
|
||||
external_id: "external_id3",
|
||||
});
|
||||
const user3 = await makeTestUser(source, {
|
||||
account_id: account1.account.id,
|
||||
role: `${USER_ROLES.TYPIST}`,
|
||||
external_id: "external_id4",
|
||||
});
|
||||
|
||||
// 更新対象ではないユーザー(まだ有効期限が残っている)
|
||||
@ -90,10 +102,11 @@ describe("licenseAutoAllocation", () => {
|
||||
const user7 = await makeTestUser(source, {
|
||||
account_id: account1.account.id,
|
||||
role: `${USER_ROLES.NONE}`,
|
||||
external_id: "external_id5",
|
||||
});
|
||||
|
||||
// 割り当て済みで有効期限が本日のライセンス
|
||||
await createLicense(
|
||||
await createAndAllocateLicense(
|
||||
source,
|
||||
1,
|
||||
currentDateEndTime,
|
||||
@ -105,7 +118,7 @@ describe("licenseAutoAllocation", () => {
|
||||
null,
|
||||
null
|
||||
);
|
||||
await createLicense(
|
||||
await createAndAllocateLicense(
|
||||
source,
|
||||
2,
|
||||
currentDateEndTime,
|
||||
@ -117,7 +130,7 @@ describe("licenseAutoAllocation", () => {
|
||||
null,
|
||||
null
|
||||
);
|
||||
await createLicense(
|
||||
await createAndAllocateLicense(
|
||||
source,
|
||||
3,
|
||||
currentDateEndTime,
|
||||
@ -129,7 +142,7 @@ describe("licenseAutoAllocation", () => {
|
||||
null,
|
||||
null
|
||||
);
|
||||
await createLicense(
|
||||
await createAndAllocateLicense(
|
||||
source,
|
||||
20,
|
||||
currentDateEndTime,
|
||||
@ -141,7 +154,7 @@ describe("licenseAutoAllocation", () => {
|
||||
null,
|
||||
null
|
||||
);
|
||||
await createLicense(
|
||||
await createAndAllocateLicense(
|
||||
source,
|
||||
5,
|
||||
currentDateEndTime,
|
||||
@ -153,7 +166,7 @@ describe("licenseAutoAllocation", () => {
|
||||
null,
|
||||
null
|
||||
);
|
||||
await createLicense(
|
||||
await createAndAllocateLicense(
|
||||
source,
|
||||
6,
|
||||
currentDateEndTime,
|
||||
@ -165,7 +178,7 @@ describe("licenseAutoAllocation", () => {
|
||||
null,
|
||||
null
|
||||
);
|
||||
await createLicense(
|
||||
await createAndAllocateLicense(
|
||||
source,
|
||||
7,
|
||||
currentDateEndTime,
|
||||
@ -183,7 +196,7 @@ describe("licenseAutoAllocation", () => {
|
||||
nextDate.setDate(nextDate.getDate() + 1);
|
||||
nextDate.setHours(23, 59, 59); // 時分秒を"23:59:59"に固定
|
||||
nextDate.setMilliseconds(0);
|
||||
await createLicense(
|
||||
await createAndAllocateLicense(
|
||||
source,
|
||||
4,
|
||||
nextDate,
|
||||
@ -204,7 +217,7 @@ describe("licenseAutoAllocation", () => {
|
||||
date.setDate(date.getDate() + i);
|
||||
date.setHours(23, 59, 59); // 時分秒を"23:59:59"に固定
|
||||
date.setMilliseconds(0);
|
||||
await createLicense(
|
||||
await createAndAllocateLicense(
|
||||
source,
|
||||
i + 100,
|
||||
date,
|
||||
@ -222,7 +235,7 @@ describe("licenseAutoAllocation", () => {
|
||||
date.setDate(date.getDate() + 30);
|
||||
date.setHours(23, 59, 59); // 時分秒を"23:59:59"に固定
|
||||
date.setMilliseconds(0);
|
||||
await createLicense(
|
||||
await createAndAllocateLicense(
|
||||
source,
|
||||
200,
|
||||
date,
|
||||
@ -235,7 +248,13 @@ describe("licenseAutoAllocation", () => {
|
||||
null
|
||||
);
|
||||
|
||||
await licenseAutoAllocationProcessing(context, source);
|
||||
await licenseAutoAllocationProcessing(
|
||||
context,
|
||||
source,
|
||||
redisClient,
|
||||
sendgridMock,
|
||||
adb2cMock
|
||||
);
|
||||
const user1Allocated = await selectLicenseByAllocatedUser(source, user1.id);
|
||||
const user2Allocated = await selectLicenseByAllocatedUser(source, user2.id);
|
||||
const user3Allocated = await selectLicenseByAllocatedUser(source, user3.id);
|
||||
@ -277,11 +296,349 @@ describe("licenseAutoAllocation", () => {
|
||||
expect(licenseAllocationHistory.licenseAllocationHistory?.account_id).toBe(
|
||||
account1.account.id
|
||||
);
|
||||
expect(
|
||||
licenseAllocationHistory.licenseAllocationHistory?.switch_from_type
|
||||
).toBe("CARD");
|
||||
// メール送信が行われていることを確認
|
||||
expect(spySend).toHaveBeenCalledTimes(4);
|
||||
});
|
||||
|
||||
it("新規ライセンスがある場合でも、有効期限が本日のライセンスが自動更新されること", async () => {
|
||||
if (!source) fail();
|
||||
const context = new InvocationContext();
|
||||
const sendgridMock = new SendGridServiceMock() as SendGridService;
|
||||
const adb2cMock = new AdB2cServiceMock() as AdB2cService;
|
||||
// 呼び出し回数でテスト成否を判定
|
||||
const spySend = jest.spyOn(sendgridMock, "sendMail");
|
||||
|
||||
const currentDateEndTime = new DateWithDayEndTime();
|
||||
|
||||
// アカウント
|
||||
const account1 = await makeTestAccount(
|
||||
source,
|
||||
{ tier: 5 },
|
||||
{ role: `${USER_ROLES.NONE}`, external_id: "external_id1" }
|
||||
);
|
||||
const account2 = await makeTestAccount(
|
||||
source,
|
||||
{ tier: 5 },
|
||||
{ role: `${USER_ROLES.NONE}`, external_id: "external_id6" }
|
||||
);
|
||||
|
||||
// 更新対象のユーザー(3role分)
|
||||
const testNoneUser1 = await makeTestUser(source, {
|
||||
account_id: account1.account.id,
|
||||
role: `${USER_ROLES.NONE}`,
|
||||
external_id: "external_id2",
|
||||
});
|
||||
const testAuthorUser2 = await makeTestUser(source, {
|
||||
account_id: account1.account.id,
|
||||
role: `${USER_ROLES.AUTHOR}`,
|
||||
external_id: "external_id3",
|
||||
});
|
||||
const testTypistUser3 = await makeTestUser(source, {
|
||||
account_id: account1.account.id,
|
||||
role: `${USER_ROLES.TYPIST}`,
|
||||
external_id: "external_id4",
|
||||
});
|
||||
|
||||
// 更新対象ではないユーザー(まだ有効期限が残っている)
|
||||
const testNoneUser4ExpirationRemain = await makeTestUser(source, {
|
||||
account_id: account1.account.id,
|
||||
role: `${USER_ROLES.NONE}`,
|
||||
});
|
||||
|
||||
// 更新対象ではないユーザー(auto_renewがfalse)
|
||||
const testNoneUser5AutoRenewFalse = await makeTestUser(source, {
|
||||
account_id: account1.account.id,
|
||||
role: `${USER_ROLES.NONE}`,
|
||||
auto_renew: false,
|
||||
});
|
||||
// 更新対象のユーザー(Author二人目)
|
||||
const testAuthorUser6 = await makeTestUser(source, {
|
||||
account_id: account1.account.id,
|
||||
role: `${USER_ROLES.AUTHOR}`,
|
||||
external_id: "external_id5",
|
||||
});
|
||||
// 更新対象のユーザー(ただしライセンスが足りない)
|
||||
const testNoneUser7lackofLicenses = await makeTestUser(source, {
|
||||
account_id: account1.account.id,
|
||||
role: `${USER_ROLES.NONE}`,
|
||||
});
|
||||
|
||||
// 割り当て済みで有効期限が本日のライセンス
|
||||
await createAndAllocateLicense(
|
||||
source,
|
||||
1,
|
||||
currentDateEndTime,
|
||||
account1.account.id,
|
||||
LICENSE_TYPE.CARD,
|
||||
LICENSE_ALLOCATED_STATUS.ALLOCATED,
|
||||
testNoneUser1.id,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
await createAndAllocateLicense(
|
||||
source,
|
||||
2,
|
||||
currentDateEndTime,
|
||||
account1.account.id,
|
||||
LICENSE_TYPE.NORMAL,
|
||||
LICENSE_ALLOCATED_STATUS.ALLOCATED,
|
||||
testAuthorUser2.id,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
await createAndAllocateLicense(
|
||||
source,
|
||||
3,
|
||||
currentDateEndTime,
|
||||
account1.account.id,
|
||||
LICENSE_TYPE.TRIAL,
|
||||
LICENSE_ALLOCATED_STATUS.ALLOCATED,
|
||||
testTypistUser3.id,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
await createAndAllocateLicense(
|
||||
source,
|
||||
20,
|
||||
currentDateEndTime,
|
||||
account2.account.id,
|
||||
LICENSE_TYPE.CARD,
|
||||
LICENSE_ALLOCATED_STATUS.ALLOCATED,
|
||||
account2.admin.id,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
await createAndAllocateLicense(
|
||||
source,
|
||||
5,
|
||||
currentDateEndTime,
|
||||
account1.account.id,
|
||||
LICENSE_TYPE.CARD,
|
||||
LICENSE_ALLOCATED_STATUS.ALLOCATED,
|
||||
testNoneUser5AutoRenewFalse.id,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
await createAndAllocateLicense(
|
||||
source,
|
||||
6,
|
||||
currentDateEndTime,
|
||||
account1.account.id,
|
||||
LICENSE_TYPE.CARD,
|
||||
LICENSE_ALLOCATED_STATUS.ALLOCATED,
|
||||
testAuthorUser6.id,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
await createAndAllocateLicense(
|
||||
source,
|
||||
7,
|
||||
currentDateEndTime,
|
||||
account1.account.id,
|
||||
LICENSE_TYPE.CARD,
|
||||
LICENSE_ALLOCATED_STATUS.ALLOCATED,
|
||||
testNoneUser7lackofLicenses.id,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
|
||||
// 割り当て済みの更新対象ではないライセンス
|
||||
const nextDate = new Date();
|
||||
nextDate.setDate(nextDate.getDate() + 1);
|
||||
nextDate.setHours(23, 59, 59); // 時分秒を"23:59:59"に固定
|
||||
nextDate.setMilliseconds(0);
|
||||
await createAndAllocateLicense(
|
||||
source,
|
||||
4,
|
||||
nextDate,
|
||||
account1.account.id,
|
||||
LICENSE_TYPE.CARD,
|
||||
LICENSE_ALLOCATED_STATUS.ALLOCATED,
|
||||
testNoneUser4ExpirationRemain.id,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
|
||||
// 有効期限が先のライセンスを作成
|
||||
// idが100のものは有効期限が当日なので自動割り当て対象外
|
||||
// idが101のものから割り当てられる
|
||||
for (let i = 0; i < 4; i++) {
|
||||
const date = new Date();
|
||||
date.setDate(date.getDate() + i);
|
||||
date.setHours(23, 59, 59); // 時分秒を"23:59:59"に固定
|
||||
date.setMilliseconds(0);
|
||||
await createAndAllocateLicense(
|
||||
source,
|
||||
i + 100,
|
||||
date,
|
||||
account1.account.id,
|
||||
LICENSE_TYPE.TRIAL,
|
||||
LICENSE_ALLOCATED_STATUS.UNALLOCATED,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
}
|
||||
// account1用の有効期限が設定されていないライセンスを作成
|
||||
await createAndAllocateLicense(
|
||||
source,
|
||||
99,
|
||||
null,
|
||||
account1.account.id,
|
||||
LICENSE_TYPE.NORMAL,
|
||||
LICENSE_ALLOCATED_STATUS.REUSABLE,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
// account2用の有効期限が設定されていないライセンスを作成
|
||||
await createAndAllocateLicense(
|
||||
source,
|
||||
200,
|
||||
null,
|
||||
account2.account.id,
|
||||
LICENSE_TYPE.CARD,
|
||||
LICENSE_ALLOCATED_STATUS.REUSABLE,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
|
||||
await licenseAutoAllocationProcessing(
|
||||
context,
|
||||
source,
|
||||
redisClient,
|
||||
sendgridMock,
|
||||
adb2cMock
|
||||
);
|
||||
const testNoneUser1Allocated = await selectLicenseByAllocatedUser(
|
||||
source,
|
||||
testNoneUser1.id
|
||||
);
|
||||
const testAuthorUser2Allocated = await selectLicenseByAllocatedUser(
|
||||
source,
|
||||
testAuthorUser2.id
|
||||
);
|
||||
const testTypistUser3Allocated = await selectLicenseByAllocatedUser(
|
||||
source,
|
||||
testTypistUser3.id
|
||||
);
|
||||
const testNoneUser4ExpirationRemainAllocated =
|
||||
await selectLicenseByAllocatedUser(
|
||||
source,
|
||||
testNoneUser4ExpirationRemain.id
|
||||
);
|
||||
const testNoneUser5AutoRenewFalseAllocated =
|
||||
await selectLicenseByAllocatedUser(
|
||||
source,
|
||||
testNoneUser5AutoRenewFalse.id
|
||||
);
|
||||
const testAuthorUser6Allocated = await selectLicenseByAllocatedUser(
|
||||
source,
|
||||
testAuthorUser6.id
|
||||
);
|
||||
const testNoneUser7lackofLicensesAllocated =
|
||||
await selectLicenseByAllocatedUser(
|
||||
source,
|
||||
testNoneUser7lackofLicenses.id
|
||||
);
|
||||
const admin2Allocated = await selectLicenseByAllocatedUser(
|
||||
source,
|
||||
account2.admin.id
|
||||
);
|
||||
const testNoneUser1LicenseAllocationHistory =
|
||||
await selectLicenseAllocationHistory(source, testNoneUser1.id, 99);
|
||||
const testAuthorUser2LicenseAllocationHistory =
|
||||
await selectLicenseAllocationHistory(source, testAuthorUser2.id, 101);
|
||||
const testTypistUser3LicenseAllocationHistory =
|
||||
await selectLicenseAllocationHistory(source, testTypistUser3.id, 103);
|
||||
|
||||
// Author、Typist、Noneの優先順位で割り当てられていることを確認
|
||||
// 複数Authorがいる場合、それぞれに割り当てられていることを確認
|
||||
expect(testAuthorUser2Allocated.license?.id).toBe(101);
|
||||
expect(testAuthorUser6Allocated.license?.id).toBe(102);
|
||||
expect(testTypistUser3Allocated.license?.id).toBe(103);
|
||||
expect(testNoneUser1Allocated.license?.id).toBe(99);
|
||||
// 有効期限がまだあるので、ライセンスが更新されていないことを確認
|
||||
expect(testNoneUser4ExpirationRemainAllocated.license?.id).toBe(4);
|
||||
// auto_renewがfalseなので、ライセンスが更新されていないことを確認
|
||||
expect(testNoneUser5AutoRenewFalseAllocated.license?.id).toBe(5);
|
||||
// ライセンスが足りない場合、ライセンスが更新されていないことを確認
|
||||
expect(testNoneUser7lackofLicensesAllocated.license?.id).toBe(7);
|
||||
// 複数アカウント分の処理が正常に行われていることの確認
|
||||
expect(admin2Allocated.license?.id).toBe(200);
|
||||
|
||||
// ライセンス割り当て履歴テーブルが更新されていることを確認
|
||||
expect(
|
||||
testNoneUser1LicenseAllocationHistory.licenseAllocationHistory?.user_id
|
||||
).toBe(testNoneUser1.id);
|
||||
expect(
|
||||
testNoneUser1LicenseAllocationHistory.licenseAllocationHistory
|
||||
?.is_allocated
|
||||
).toBe(true);
|
||||
expect(
|
||||
testNoneUser1LicenseAllocationHistory.licenseAllocationHistory?.account_id
|
||||
).toBe(account1.account.id);
|
||||
expect(
|
||||
testNoneUser1LicenseAllocationHistory.licenseAllocationHistory
|
||||
?.switch_from_type
|
||||
).toBe("CARD");
|
||||
expect(
|
||||
testAuthorUser2LicenseAllocationHistory.licenseAllocationHistory?.user_id
|
||||
).toBe(testAuthorUser2.id);
|
||||
expect(
|
||||
testAuthorUser2LicenseAllocationHistory.licenseAllocationHistory
|
||||
?.is_allocated
|
||||
).toBe(true);
|
||||
expect(
|
||||
testAuthorUser2LicenseAllocationHistory.licenseAllocationHistory
|
||||
?.account_id
|
||||
).toBe(account1.account.id);
|
||||
expect(
|
||||
testAuthorUser2LicenseAllocationHistory.licenseAllocationHistory
|
||||
?.switch_from_type
|
||||
).toBe("NONE");
|
||||
expect(
|
||||
testTypistUser3LicenseAllocationHistory.licenseAllocationHistory?.user_id
|
||||
).toBe(testTypistUser3.id);
|
||||
expect(
|
||||
testTypistUser3LicenseAllocationHistory.licenseAllocationHistory
|
||||
?.is_allocated
|
||||
).toBe(true);
|
||||
expect(
|
||||
testTypistUser3LicenseAllocationHistory.licenseAllocationHistory
|
||||
?.account_id
|
||||
).toBe(account1.account.id);
|
||||
expect(
|
||||
testTypistUser3LicenseAllocationHistory.licenseAllocationHistory
|
||||
?.switch_from_type
|
||||
).toBe("TRIAL");
|
||||
// メール送信が行われていることを確認
|
||||
expect(spySend).toHaveBeenCalledTimes(5);
|
||||
});
|
||||
|
||||
it("有効期限が指定日のライセンスが自動更新されること(リトライ用)", async () => {
|
||||
if (!source) fail();
|
||||
const context = new InvocationContext();
|
||||
const sendgridMock = new SendGridServiceMock() as SendGridService;
|
||||
const adb2cMock = new AdB2cServiceMock() as AdB2cService;
|
||||
// 呼び出し回数でテスト成否を判定
|
||||
const spySend = jest.spyOn(sendgridMock, "sendMail");
|
||||
|
||||
// 2023/11/22の日付を作成
|
||||
const date1122 = new Date(2023, 10, 22, 23, 59, 59);
|
||||
const currentDateEndTime = new DateWithDayEndTime(date1122);
|
||||
@ -289,26 +646,29 @@ describe("licenseAutoAllocation", () => {
|
||||
const account1 = await makeTestAccount(
|
||||
source,
|
||||
{ tier: 5 },
|
||||
{ role: `${USER_ROLES.NONE}` }
|
||||
{ role: `${USER_ROLES.NONE}`, external_id: "external_id1" }
|
||||
);
|
||||
const account2 = await makeTestAccount(
|
||||
source,
|
||||
{ tier: 5 },
|
||||
{ role: `${USER_ROLES.NONE}` }
|
||||
{ role: `${USER_ROLES.NONE}`, external_id: "external_id6" }
|
||||
);
|
||||
|
||||
// 更新対象のユーザー(3role分)
|
||||
const user1 = await makeTestUser(source, {
|
||||
account_id: account1.account.id,
|
||||
role: `${USER_ROLES.NONE}`,
|
||||
external_id: "external_id2",
|
||||
});
|
||||
const user2 = await makeTestUser(source, {
|
||||
account_id: account1.account.id,
|
||||
role: `${USER_ROLES.AUTHOR}`,
|
||||
external_id: "external_id3",
|
||||
});
|
||||
const user3 = await makeTestUser(source, {
|
||||
account_id: account1.account.id,
|
||||
role: `${USER_ROLES.TYPIST}`,
|
||||
external_id: "external_id4",
|
||||
});
|
||||
|
||||
// 更新対象ではないユーザー(まだ有効期限が残っている)
|
||||
@ -325,7 +685,7 @@ describe("licenseAutoAllocation", () => {
|
||||
});
|
||||
|
||||
// 割り当て済みで有効期限が11/22のライセンス
|
||||
await createLicense(
|
||||
await createAndAllocateLicense(
|
||||
source,
|
||||
1,
|
||||
currentDateEndTime,
|
||||
@ -337,7 +697,7 @@ describe("licenseAutoAllocation", () => {
|
||||
null,
|
||||
null
|
||||
);
|
||||
await createLicense(
|
||||
await createAndAllocateLicense(
|
||||
source,
|
||||
2,
|
||||
currentDateEndTime,
|
||||
@ -349,7 +709,7 @@ describe("licenseAutoAllocation", () => {
|
||||
null,
|
||||
null
|
||||
);
|
||||
await createLicense(
|
||||
await createAndAllocateLicense(
|
||||
source,
|
||||
3,
|
||||
currentDateEndTime,
|
||||
@ -361,7 +721,7 @@ describe("licenseAutoAllocation", () => {
|
||||
null,
|
||||
null
|
||||
);
|
||||
await createLicense(
|
||||
await createAndAllocateLicense(
|
||||
source,
|
||||
20,
|
||||
currentDateEndTime,
|
||||
@ -373,7 +733,7 @@ describe("licenseAutoAllocation", () => {
|
||||
null,
|
||||
null
|
||||
);
|
||||
await createLicense(
|
||||
await createAndAllocateLicense(
|
||||
source,
|
||||
5,
|
||||
currentDateEndTime,
|
||||
@ -390,7 +750,7 @@ describe("licenseAutoAllocation", () => {
|
||||
nextDate.setDate(date1122.getDate() + 1);
|
||||
nextDate.setHours(23, 59, 59); // 時分秒を"23:59:59"に固定
|
||||
nextDate.setMilliseconds(0);
|
||||
await createLicense(
|
||||
await createAndAllocateLicense(
|
||||
source,
|
||||
4,
|
||||
nextDate,
|
||||
@ -409,7 +769,7 @@ describe("licenseAutoAllocation", () => {
|
||||
// 2023/11/22の日付を作成
|
||||
const date = new Date(2023, 10, 22, 23, 59, 59);
|
||||
date.setDate(date.getDate() + i);
|
||||
await createLicense(
|
||||
await createAndAllocateLicense(
|
||||
source,
|
||||
i + 100,
|
||||
date,
|
||||
@ -427,7 +787,7 @@ describe("licenseAutoAllocation", () => {
|
||||
dateMarch31.setMonth(12);
|
||||
dateMarch31.setHours(23, 59, 59); // 時分秒を"23:59:59"に固定
|
||||
dateMarch31.setMilliseconds(0);
|
||||
await createLicense(
|
||||
await createAndAllocateLicense(
|
||||
source,
|
||||
200,
|
||||
dateMarch31,
|
||||
@ -439,7 +799,14 @@ describe("licenseAutoAllocation", () => {
|
||||
null,
|
||||
null
|
||||
);
|
||||
await licenseAutoAllocationProcessing(context, source, date1122);
|
||||
await licenseAutoAllocationProcessing(
|
||||
context,
|
||||
source,
|
||||
redisClient,
|
||||
sendgridMock,
|
||||
adb2cMock,
|
||||
date1122
|
||||
);
|
||||
const user1Allocated = await selectLicenseByAllocatedUser(source, user1.id);
|
||||
const user2Allocated = await selectLicenseByAllocatedUser(source, user2.id);
|
||||
const user3Allocated = await selectLicenseByAllocatedUser(source, user3.id);
|
||||
@ -475,36 +842,50 @@ describe("licenseAutoAllocation", () => {
|
||||
expect(licenseAllocationHistory.licenseAllocationHistory?.account_id).toBe(
|
||||
account1.account.id
|
||||
);
|
||||
// メール送信が行われていることを確認
|
||||
expect(spySend).toHaveBeenCalledTimes(4);
|
||||
});
|
||||
it("新たに割り当てられるライセンスが存在しないため、ライセンスが自動更新されない(エラーではない)", async () => {
|
||||
it("新たに割り当てられるライセンスが存在しないアカウントは、ライセンスが自動更新されない(エラーではない)", async () => {
|
||||
if (!source) fail();
|
||||
const context = new InvocationContext();
|
||||
const sendgridMock = new SendGridServiceMock() as SendGridService;
|
||||
const adb2cMock = new AdB2cServiceMock() as AdB2cService;
|
||||
// 呼び出し回数でテスト成否を判定
|
||||
const spySend = jest.spyOn(sendgridMock, "sendMail");
|
||||
|
||||
const currentDateEndTime = new DateWithDayEndTime();
|
||||
|
||||
// アカウント
|
||||
// アカウントと管理者
|
||||
const account1 = await makeTestAccount(
|
||||
source,
|
||||
{ tier: 5 },
|
||||
{ role: `${USER_ROLES.NONE}` }
|
||||
{ role: `${USER_ROLES.NONE}`, external_id: "external_id1" }
|
||||
);
|
||||
const account2 = await makeTestAccount(
|
||||
source,
|
||||
{ tier: 5 },
|
||||
{ role: `${USER_ROLES.NONE}`, external_id: "external_id5" }
|
||||
);
|
||||
|
||||
// 更新対象のユーザー(3role分)
|
||||
// account1の更新対象のユーザー(3role分)
|
||||
const user1 = await makeTestUser(source, {
|
||||
account_id: account1.account.id,
|
||||
role: `${USER_ROLES.NONE}`,
|
||||
external_id: "external_id2",
|
||||
});
|
||||
const user2 = await makeTestUser(source, {
|
||||
account_id: account1.account.id,
|
||||
role: `${USER_ROLES.AUTHOR}`,
|
||||
external_id: "external_id3",
|
||||
});
|
||||
const user3 = await makeTestUser(source, {
|
||||
account_id: account1.account.id,
|
||||
role: `${USER_ROLES.TYPIST}`,
|
||||
external_id: "external_id4",
|
||||
});
|
||||
|
||||
// 割り当て済みで有効期限が本日のライセンス
|
||||
await createLicense(
|
||||
await createAndAllocateLicense(
|
||||
source,
|
||||
1,
|
||||
currentDateEndTime,
|
||||
@ -516,7 +897,7 @@ describe("licenseAutoAllocation", () => {
|
||||
null,
|
||||
null
|
||||
);
|
||||
await createLicense(
|
||||
await createAndAllocateLicense(
|
||||
source,
|
||||
2,
|
||||
currentDateEndTime,
|
||||
@ -528,7 +909,7 @@ describe("licenseAutoAllocation", () => {
|
||||
null,
|
||||
null
|
||||
);
|
||||
await createLicense(
|
||||
await createAndAllocateLicense(
|
||||
source,
|
||||
3,
|
||||
currentDateEndTime,
|
||||
@ -540,20 +921,67 @@ describe("licenseAutoAllocation", () => {
|
||||
null,
|
||||
null
|
||||
);
|
||||
await createAndAllocateLicense(
|
||||
source,
|
||||
4,
|
||||
currentDateEndTime,
|
||||
account2.account.id,
|
||||
LICENSE_TYPE.TRIAL,
|
||||
LICENSE_ALLOCATED_STATUS.ALLOCATED,
|
||||
account2.admin.id,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
|
||||
await licenseAutoAllocationProcessing(context, source);
|
||||
// account2の有効期限が先の未割当ライセンスを作成
|
||||
const nextDate = new Date();
|
||||
nextDate.setDate(nextDate.getDate() + 1);
|
||||
nextDate.setHours(23, 59, 59); // 時分秒を"23:59:59"に固定
|
||||
nextDate.setMilliseconds(0);
|
||||
await createAndAllocateLicense(
|
||||
source,
|
||||
100,
|
||||
nextDate,
|
||||
account2.account.id,
|
||||
LICENSE_TYPE.NORMAL,
|
||||
LICENSE_ALLOCATED_STATUS.UNALLOCATED,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
|
||||
await licenseAutoAllocationProcessing(
|
||||
context,
|
||||
source,
|
||||
redisClient,
|
||||
sendgridMock,
|
||||
adb2cMock
|
||||
);
|
||||
const user1Allocated = await selectLicenseByAllocatedUser(source, user1.id);
|
||||
const user2Allocated = await selectLicenseByAllocatedUser(source, user2.id);
|
||||
const user3Allocated = await selectLicenseByAllocatedUser(source, user3.id);
|
||||
const account2AdminAllocated = await selectLicenseByAllocatedUser(
|
||||
source,
|
||||
account2.admin.id
|
||||
);
|
||||
// ライセンスが更新されていないことを確認
|
||||
expect(user1Allocated.license?.id).toBe(1);
|
||||
expect(user2Allocated.license?.id).toBe(2);
|
||||
expect(user3Allocated.license?.id).toBe(3);
|
||||
expect(account2AdminAllocated.license?.id).toBe(100);
|
||||
// メール送信が行われていないことを確認
|
||||
expect(spySend).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("tier4のアカウントのため、ライセンスが自動更新されない", async () => {
|
||||
if (!source) fail();
|
||||
const context = new InvocationContext();
|
||||
const sendgridMock = new SendGridServiceMock() as SendGridService;
|
||||
const adb2cMock = new AdB2cServiceMock() as AdB2cService;
|
||||
// 呼び出し回数でテスト成否を判定
|
||||
const spySend = jest.spyOn(sendgridMock, "sendMail");
|
||||
|
||||
const currentDateEndTime = new DateWithDayEndTime();
|
||||
|
||||
@ -561,25 +989,28 @@ describe("licenseAutoAllocation", () => {
|
||||
const account1 = await makeTestAccount(
|
||||
source,
|
||||
{ tier: 4 },
|
||||
{ role: `${USER_ROLES.NONE}` }
|
||||
{ role: `${USER_ROLES.NONE}`, external_id: "external_id1" }
|
||||
);
|
||||
|
||||
// 更新対象のユーザー(3role分)
|
||||
const user1 = await makeTestUser(source, {
|
||||
account_id: account1.account.id,
|
||||
role: `${USER_ROLES.NONE}`,
|
||||
external_id: "external_id2",
|
||||
});
|
||||
const user2 = await makeTestUser(source, {
|
||||
account_id: account1.account.id,
|
||||
role: `${USER_ROLES.AUTHOR}`,
|
||||
external_id: "external_id3",
|
||||
});
|
||||
const user3 = await makeTestUser(source, {
|
||||
account_id: account1.account.id,
|
||||
role: `${USER_ROLES.TYPIST}`,
|
||||
external_id: "external_id4",
|
||||
});
|
||||
|
||||
// 割り当て済みで有効期限が本日のライセンス
|
||||
await createLicense(
|
||||
await createAndAllocateLicense(
|
||||
source,
|
||||
1,
|
||||
currentDateEndTime,
|
||||
@ -591,7 +1022,7 @@ describe("licenseAutoAllocation", () => {
|
||||
null,
|
||||
null
|
||||
);
|
||||
await createLicense(
|
||||
await createAndAllocateLicense(
|
||||
source,
|
||||
2,
|
||||
currentDateEndTime,
|
||||
@ -603,7 +1034,7 @@ describe("licenseAutoAllocation", () => {
|
||||
null,
|
||||
null
|
||||
);
|
||||
await createLicense(
|
||||
await createAndAllocateLicense(
|
||||
source,
|
||||
3,
|
||||
currentDateEndTime,
|
||||
@ -624,7 +1055,7 @@ describe("licenseAutoAllocation", () => {
|
||||
date.setDate(date.getDate() + i);
|
||||
date.setHours(23, 59, 59); // 時分秒を"23:59:59"に固定
|
||||
date.setMilliseconds(0);
|
||||
await createLicense(
|
||||
await createAndAllocateLicense(
|
||||
source,
|
||||
i + 100,
|
||||
date,
|
||||
@ -638,7 +1069,13 @@ describe("licenseAutoAllocation", () => {
|
||||
);
|
||||
}
|
||||
|
||||
await licenseAutoAllocationProcessing(context, source);
|
||||
await licenseAutoAllocationProcessing(
|
||||
context,
|
||||
source,
|
||||
redisClient,
|
||||
sendgridMock,
|
||||
adb2cMock
|
||||
);
|
||||
const user1Allocated = await selectLicenseByAllocatedUser(source, user1.id);
|
||||
const user2Allocated = await selectLicenseByAllocatedUser(source, user2.id);
|
||||
const user3Allocated = await selectLicenseByAllocatedUser(source, user3.id);
|
||||
@ -646,5 +1083,99 @@ describe("licenseAutoAllocation", () => {
|
||||
expect(user1Allocated.license?.id).toBe(1);
|
||||
expect(user2Allocated.license?.id).toBe(2);
|
||||
expect(user3Allocated.license?.id).toBe(3);
|
||||
// メール送信が行われていないことを確認
|
||||
expect(spySend).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
it("メール送信に失敗しても、有効期限が本日のライセンスが自動更新されること", async () => {
|
||||
if (!source) fail();
|
||||
const context = new InvocationContext();
|
||||
const sendgridMock = new SendGridServiceMock() as SendGridService;
|
||||
const adb2cMock = new AdB2cServiceMock() as AdB2cService;
|
||||
// 呼び出し回数でテスト成否を判定
|
||||
const spySend = jest.spyOn(sendgridMock, "sendMail");
|
||||
const currentDateEndTime = new DateWithDayEndTime();
|
||||
|
||||
// アカウント
|
||||
const account1 = await makeTestAccount(
|
||||
source,
|
||||
{ tier: 5 },
|
||||
{ role: `${USER_ROLES.NONE}`, external_id: "external_id1" }
|
||||
);
|
||||
|
||||
// 更新対象のユーザー(3role分)
|
||||
const user1 = await makeTestUser(source, {
|
||||
account_id: account1.account.id,
|
||||
role: `${USER_ROLES.NONE}`,
|
||||
external_id: "external_id7", // メール送信失敗用
|
||||
});
|
||||
// 割り当て済みで有効期限が本日のライセンス
|
||||
await createAndAllocateLicense(
|
||||
source,
|
||||
1,
|
||||
currentDateEndTime,
|
||||
account1.account.id,
|
||||
LICENSE_TYPE.CARD,
|
||||
LICENSE_ALLOCATED_STATUS.ALLOCATED,
|
||||
user1.id,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
|
||||
// 有効期限が先の未割当ライセンスを作成
|
||||
// idが100のものは有効期限が当日なので自動割り当て対象外
|
||||
// idが101のものから割り当てられる
|
||||
for (let i = 0; i < 5; i++) {
|
||||
const date = new Date();
|
||||
date.setDate(date.getDate() + i);
|
||||
date.setHours(23, 59, 59); // 時分秒を"23:59:59"に固定
|
||||
date.setMilliseconds(0);
|
||||
await createAndAllocateLicense(
|
||||
source,
|
||||
i + 100,
|
||||
date,
|
||||
account1.account.id,
|
||||
LICENSE_TYPE.CARD,
|
||||
LICENSE_ALLOCATED_STATUS.UNALLOCATED,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
await licenseAutoAllocationProcessing(
|
||||
context,
|
||||
source,
|
||||
redisClient,
|
||||
sendgridMock,
|
||||
adb2cMock
|
||||
);
|
||||
const user1Allocated = await selectLicenseByAllocatedUser(source, user1.id);
|
||||
|
||||
const licenseAllocationHistory = await selectLicenseAllocationHistory(
|
||||
source,
|
||||
user1.id,
|
||||
101
|
||||
);
|
||||
// 割り当てられていることを確認
|
||||
expect(user1Allocated.license?.id).toBe(101);
|
||||
|
||||
// ライセンス割り当て履歴テーブルが更新されていることを確認
|
||||
expect(licenseAllocationHistory.licenseAllocationHistory?.user_id).toBe(
|
||||
user1.id
|
||||
);
|
||||
expect(
|
||||
licenseAllocationHistory.licenseAllocationHistory?.is_allocated
|
||||
).toBe(true);
|
||||
expect(licenseAllocationHistory.licenseAllocationHistory?.account_id).toBe(
|
||||
account1.account.id
|
||||
);
|
||||
expect(
|
||||
licenseAllocationHistory.licenseAllocationHistory?.switch_from_type
|
||||
).toBe("CARD");
|
||||
// メール送信が行われていないことを確認
|
||||
expect(spySend).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"target": "es6",
|
||||
"target": "ES2021",
|
||||
"outDir": "dist",
|
||||
"rootDir": ".",
|
||||
"sourceMap": true,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user