diff --git a/dictation_server/src/constants/index.ts b/dictation_server/src/constants/index.ts index a4bd53b..a42d017 100644 --- a/dictation_server/src/constants/index.ts +++ b/dictation_server/src/constants/index.ts @@ -204,3 +204,15 @@ export const USER_LICENSE_STATUS = { ALERT: 'Alert', RENEW: 'Renew', }; + +/** + *トライアルライセンスの有効期限(日数) + * @const {number} + */ +export const TRIAL_LICENSE_EXPIRATION_DAYS = 30; + +/** + * ライセンスの発行数 + * @const {number} + */ +export const TRIAL_LICENSE_ISSUE_NUM = 100; diff --git a/dictation_server/src/features/users/test/utility.ts b/dictation_server/src/features/users/test/utility.ts index 31a8a34..cb3a442 100644 --- a/dictation_server/src/features/users/test/utility.ts +++ b/dictation_server/src/features/users/test/utility.ts @@ -68,6 +68,7 @@ export const createUser = async ( encryption?: boolean | undefined, encryption_password?: string | undefined, prompt?: boolean | undefined, + email_verified?: boolean | undefined, ): Promise<{ userId: number; externalId: string }> => { const { identifiers } = await datasource.getRepository(User).insert({ account_id: accountId, @@ -75,7 +76,7 @@ export const createUser = async ( role: role, accepted_terms_version: '1.0', author_id: author_id, - email_verified: true, + email_verified: email_verified ?? true, auto_renew: auto_renew, license_alert: true, notification: true, @@ -103,6 +104,18 @@ export const getUser = async ( return user; }; +export const getLicenses = async ( + datasource: DataSource, + account_id: number, +): Promise => { + const licenses = await datasource.getRepository(License).find({ + where: { + account_id: account_id, + }, + }); + return licenses; +}; + /** * * @param datasource diff --git a/dictation_server/src/features/users/users.service.spec.ts b/dictation_server/src/features/users/users.service.spec.ts index 5ef0969..cbce69f 100644 --- a/dictation_server/src/features/users/users.service.spec.ts +++ b/dictation_server/src/features/users/users.service.spec.ts @@ -15,40 +15,166 @@ import { createLicense, createUser, createUserGroup, + getLicenses, getUser, makeTestingModuleWithAdb2c, } from './test/utility'; import { DataSource } from 'typeorm'; import { UsersService } from './users.service'; import { + LICENSE_ALLOCATED_STATUS, LICENSE_EXPIRATION_THRESHOLD_DAYS, + LICENSE_TYPE, + TRIAL_LICENSE_EXPIRATION_DAYS, USER_LICENSE_STATUS, USER_ROLES, } from '../../constants'; import { makeTestingModule } from '../../common/test/modules'; +import { ExpirationThresholdDate } from '../licenses/types/types'; +import { License } from '../../repositories/licenses/entity/license.entity'; describe('UsersService.confirmUser', () => { - it('ユーザの仮登録時に払い出されるトークンにより、未認証のユーザが認証済みになる', async () => { - const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue(); - const licensesRepositoryMockValue = null; - const adb2cParam = makeDefaultAdB2cMockValue(); - const sendGridMockValue = makeDefaultSendGridlValue(); - const configMockValue = makeDefaultConfigValue(); - const sortCriteriaRepositoryMockValue = - makeDefaultSortCriteriaRepositoryMockValue(); - const service = await makeUsersServiceMock( - usersRepositoryMockValue, - licensesRepositoryMockValue, - adb2cParam, - sendGridMockValue, - configMockValue, - sortCriteriaRepositoryMockValue, - ); - const token = - 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2NvdW50SWQiOjEsInVzZXJJZCI6MiwiZW1haWwiOiJ4eHhAeHh4Lnh4eCIsImlhdCI6MTAwMDAwMDAwMCwiZXhwIjo5MDAwMDAwMDAwfQ.26L6BdNg-3TbyKT62PswlJ6RPMkcTtHzlDXW2Uo9XbMPVSrl2ObcuS6EcXjFFN2DEfNTKbqX_zevIWMpHOAdLNgGhk528nLrBrNvPASqtTjvW9muxMXpjUdjRVkmVbOylBHWW3YpWL9JEbJQ7rAzWDfaIdPhMovdaxumnZt_UwnlnrdaVPLACW7tkH_laEcAU507iSiM4mqxxG8FuTs34t6PEdwRuzZAQPN2IOPYNSvGNdJYryPacSeSNZ_z1xeBYXLOLQfOBZzyTReYDOhXdikhrNUbxjgnZQlSXBCVMlZ9PH42bHfp-LJIeJzW0yqnF6oLklvJP-fo8eW0k5iDOw'; - expect(await service.confirmUser(token)).toEqual(undefined); + let source: DataSource = null; + beforeEach(async () => { + source = new DataSource({ + type: 'sqlite', + database: ':memory:', + entities: [__dirname + '/../../**/*.entity{.ts,.js}'], + synchronize: true, // trueにすると自動的にmigrationが行われるため注意 + }); + return source.initialize(); + }); + afterEach(async () => { + await source.destroy(); + source = null; }); + it('ユーザの仮登録時に払い出されるトークンにより、未認証のユーザが認証済みになり、トライアルライセンスが100件作成される', async () => { + const module = await makeTestingModule(source); + const { accountId } = await createAccount(source); + await createUser( + source, + accountId, + 'externalId_user1', + USER_ROLES.NONE, + undefined, + true, + false, + undefined, + false, + false, + ); + const { userId } = await createUser( + source, + accountId, + 'externalId_user2', + USER_ROLES.NONE, + undefined, + true, + false, + undefined, + false, + false, + ); + + const service = module.get(UsersService); + const token = + 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2NvdW50SWQiOjEsInVzZXJJZCI6MiwiZW1haWwiOiJ4eHhAeHh4Lnh4eCIsImlhdCI6MTAwMDAwMDAwMCwiZXhwIjo5MDAwMDAwMDAwfQ.26L6BdNg-3TbyKT62PswlJ6RPMkcTtHzlDXW2Uo9XbMPVSrl2ObcuS6EcXjFFN2DEfNTKbqX_zevIWMpHOAdLNgGhk528nLrBrNvPASqtTjvW9muxMXpjUdjRVkmVbOylBHWW3YpWL9JEbJQ7rAzWDfaIdPhMovdaxumnZt_UwnlnrdaVPLACW7tkH_laEcAU507iSiM4mqxxG8FuTs34t6PEdwRuzZAQPN2IOPYNSvGNdJYryPacSeSNZ_z1xeBYXLOLQfOBZzyTReYDOhXdikhrNUbxjgnZQlSXBCVMlZ9PH42bHfp-LJIeJzW0yqnF6oLklvJP-fo8eW0k5iDOw'; + await service.confirmUser(token); + //result + const resultUser = await getUser(source, userId); + const resultLicenses = await getLicenses(source, accountId); + const today = new Date(); + // トライアルライセンスは有効期限は今日を起算日として30日後の日付が変わるまで + const expiryDate = new ExpirationThresholdDate( + today.setDate(today.getDate() + TRIAL_LICENSE_EXPIRATION_DAYS), + ); + const resultLicensesCheckParam: Omit< + License, + 'deleted_at' | 'created_by' | 'created_at' | 'updated_at' | 'updated_by' + > = { + id: 0, + expiry_date: resultLicenses[0].expiry_date, + account_id: resultLicenses[0].account_id, + type: resultLicenses[0].type, + status: resultLicenses[0].status, + allocated_user_id: resultLicenses[0].allocated_user_id, + order_id: resultLicenses[0].order_id, + delete_order_id: resultLicenses[0].delete_order_id, + }; + + expect(resultUser.email_verified).toBe(true); + expect(resultLicenses.length).toBe(100); + expect(resultLicensesCheckParam).toEqual({ + id: 0, + expiry_date: expiryDate, + account_id: accountId, + type: LICENSE_TYPE.TRIAL, + status: LICENSE_ALLOCATED_STATUS.UNALLOCATED, + allocated_user_id: null, + order_id: null, + delete_order_id: null, + }); + }); + + it('トークンの形式が不正な場合、形式不正エラーとなる。', async () => { + const module = await makeTestingModule(source); + const token = 'invalid.id.token'; + const service = module.get(UsersService); + await expect(service.confirmUser(token)).rejects.toEqual( + new HttpException(makeErrorResponse('E000101'), HttpStatus.BAD_REQUEST), + ); + }); + + it('ユーザが既に認証済みだった場合、認証済みユーザエラーとなる。', async () => { + const module = await makeTestingModule(source); + const { accountId } = await createAccount(source); + await createUser( + source, + accountId, + 'externalId_user1', + USER_ROLES.NONE, + undefined, + true, + false, + undefined, + false, + false, + ); + await createUser( + source, + accountId, + 'externalId_user2', + USER_ROLES.NONE, + undefined, + true, + false, + undefined, + false, + true, //emailを認証済みにする + ); + const service = module.get(UsersService); + const token = + 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2NvdW50SWQiOjEsInVzZXJJZCI6MiwiZW1haWwiOiJ4eHhAeHh4Lnh4eCIsImlhdCI6MTAwMDAwMDAwMCwiZXhwIjo5MDAwMDAwMDAwfQ.26L6BdNg-3TbyKT62PswlJ6RPMkcTtHzlDXW2Uo9XbMPVSrl2ObcuS6EcXjFFN2DEfNTKbqX_zevIWMpHOAdLNgGhk528nLrBrNvPASqtTjvW9muxMXpjUdjRVkmVbOylBHWW3YpWL9JEbJQ7rAzWDfaIdPhMovdaxumnZt_UwnlnrdaVPLACW7tkH_laEcAU507iSiM4mqxxG8FuTs34t6PEdwRuzZAQPN2IOPYNSvGNdJYryPacSeSNZ_z1xeBYXLOLQfOBZzyTReYDOhXdikhrNUbxjgnZQlSXBCVMlZ9PH42bHfp-LJIeJzW0yqnF6oLklvJP-fo8eW0k5iDOw'; + await expect(service.confirmUser(token)).rejects.toEqual( + new HttpException(makeErrorResponse('E010202'), HttpStatus.BAD_REQUEST), + ); + }); + it('ユーザーが存在しない場合は、想定外のエラーとなる', async () => { + const module = await makeTestingModule(source); + const service = module.get(UsersService); + const token = + 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2NvdW50SWQiOjEsInVzZXJJZCI6MiwiZW1haWwiOiJ4eHhAeHh4Lnh4eCIsImlhdCI6MTAwMDAwMDAwMCwiZXhwIjo5MDAwMDAwMDAwfQ.26L6BdNg-3TbyKT62PswlJ6RPMkcTtHzlDXW2Uo9XbMPVSrl2ObcuS6EcXjFFN2DEfNTKbqX_zevIWMpHOAdLNgGhk528nLrBrNvPASqtTjvW9muxMXpjUdjRVkmVbOylBHWW3YpWL9JEbJQ7rAzWDfaIdPhMovdaxumnZt_UwnlnrdaVPLACW7tkH_laEcAU507iSiM4mqxxG8FuTs34t6PEdwRuzZAQPN2IOPYNSvGNdJYryPacSeSNZ_z1xeBYXLOLQfOBZzyTReYDOhXdikhrNUbxjgnZQlSXBCVMlZ9PH42bHfp-LJIeJzW0yqnF6oLklvJP-fo8eW0k5iDOw'; + await expect(service.confirmUser(token)).rejects.toEqual( + new HttpException( + makeErrorResponse('E009999'), + HttpStatus.INTERNAL_SERVER_ERROR, + ), + ); + }); +}); + +describe('UsersService.confirmUserAndInitPassword', () => { it('ユーザーが発行されたパスワードでログインできるようにする', async () => { const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue(); usersRepositoryMockValue.findUserById = { @@ -88,28 +214,6 @@ describe('UsersService.confirmUser', () => { expect(await service.confirmUserAndInitPassword(token)).toEqual(undefined); }); - it('トークンの形式が不正な場合、形式不正エラーとなる。', async () => { - const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue(); - const licensesRepositoryMockValue = null; - const adb2cParam = makeDefaultAdB2cMockValue(); - const sendgridMockValue = makeDefaultSendGridlValue(); - const configMockValue = makeDefaultConfigValue(); - const sortCriteriaRepositoryMockValue = - makeDefaultSortCriteriaRepositoryMockValue(); - const service = await makeUsersServiceMock( - usersRepositoryMockValue, - licensesRepositoryMockValue, - adb2cParam, - sendgridMockValue, - configMockValue, - sortCriteriaRepositoryMockValue, - ); - const token = 'invalid.id.token'; - await expect(service.confirmUser(token)).rejects.toEqual( - new HttpException(makeErrorResponse('E000101'), HttpStatus.BAD_REQUEST), - ); - }); - it('トークンの形式が不正な場合、形式不正エラーとなる。(メール認証API)', async () => { const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue(); usersRepositoryMockValue.findUserById = { @@ -148,32 +252,6 @@ describe('UsersService.confirmUser', () => { new HttpException(makeErrorResponse('E000101'), HttpStatus.BAD_REQUEST), ); }); - it('ユーザが既に認証済みだった場合、認証済みユーザエラーとなる。', async () => { - const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue(); - const licensesRepositoryMockValue = null; - const adb2cParam = makeDefaultAdB2cMockValue(); - const sendgridMockValue = makeDefaultSendGridlValue(); - const configMockValue = makeDefaultConfigValue(); - const sortCriteriaRepositoryMockValue = - makeDefaultSortCriteriaRepositoryMockValue(); - - usersRepositoryMockValue.updateUserVerified = - new EmailAlreadyVerifiedError(); - - const service = await makeUsersServiceMock( - usersRepositoryMockValue, - licensesRepositoryMockValue, - adb2cParam, - sendgridMockValue, - configMockValue, - sortCriteriaRepositoryMockValue, - ); - const token = - 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2NvdW50SWQiOjEsInVzZXJJZCI6MiwiZW1haWwiOiJ4eHhAeHh4Lnh4eCIsImlhdCI6MTAwMDAwMDAwMCwiZXhwIjo5MDAwMDAwMDAwfQ.26L6BdNg-3TbyKT62PswlJ6RPMkcTtHzlDXW2Uo9XbMPVSrl2ObcuS6EcXjFFN2DEfNTKbqX_zevIWMpHOAdLNgGhk528nLrBrNvPASqtTjvW9muxMXpjUdjRVkmVbOylBHWW3YpWL9JEbJQ7rAzWDfaIdPhMovdaxumnZt_UwnlnrdaVPLACW7tkH_laEcAU507iSiM4mqxxG8FuTs34t6PEdwRuzZAQPN2IOPYNSvGNdJYryPacSeSNZ_z1xeBYXLOLQfOBZzyTReYDOhXdikhrNUbxjgnZQlSXBCVMlZ9PH42bHfp-LJIeJzW0yqnF6oLklvJP-fo8eW0k5iDOw'; - await expect(service.confirmUser(token)).rejects.toEqual( - new HttpException(makeErrorResponse('E010202'), HttpStatus.BAD_REQUEST), - ); - }); it('ユーザが既に認証済みだった場合、認証済みユーザエラーとなる。(メール認証API)', async () => { const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue(); usersRepositoryMockValue.findUserById = { @@ -216,33 +294,6 @@ describe('UsersService.confirmUser', () => { new HttpException(makeErrorResponse('E010202'), HttpStatus.BAD_REQUEST), ); }); - it('DBネットワークエラーとなる場合、エラーとなる。', async () => { - const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue(); - const licensesRepositoryMockValue = null; - const adb2cParam = makeDefaultAdB2cMockValue(); - const sendgridMockValue = makeDefaultSendGridlValue(); - const configMockValue = makeDefaultConfigValue(); - const sortCriteriaRepositoryMockValue = - makeDefaultSortCriteriaRepositoryMockValue(); - usersRepositoryMockValue.updateUserVerified = new Error('DB error'); - - const service = await makeUsersServiceMock( - usersRepositoryMockValue, - licensesRepositoryMockValue, - adb2cParam, - sendgridMockValue, - configMockValue, - sortCriteriaRepositoryMockValue, - ); - const token = - 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2NvdW50SWQiOjEsInVzZXJJZCI6MiwiZW1haWwiOiJ4eHhAeHh4Lnh4eCIsImlhdCI6MTAwMDAwMDAwMCwiZXhwIjo5MDAwMDAwMDAwfQ.26L6BdNg-3TbyKT62PswlJ6RPMkcTtHzlDXW2Uo9XbMPVSrl2ObcuS6EcXjFFN2DEfNTKbqX_zevIWMpHOAdLNgGhk528nLrBrNvPASqtTjvW9muxMXpjUdjRVkmVbOylBHWW3YpWL9JEbJQ7rAzWDfaIdPhMovdaxumnZt_UwnlnrdaVPLACW7tkH_laEcAU507iSiM4mqxxG8FuTs34t6PEdwRuzZAQPN2IOPYNSvGNdJYryPacSeSNZ_z1xeBYXLOLQfOBZzyTReYDOhXdikhrNUbxjgnZQlSXBCVMlZ9PH42bHfp-LJIeJzW0yqnF6oLklvJP-fo8eW0k5iDOw'; - await expect(service.confirmUser(token)).rejects.toEqual( - new HttpException( - makeErrorResponse('E009999'), - HttpStatus.INTERNAL_SERVER_ERROR, - ), - ); - }); it('DBネットワークエラーとなる場合、エラーとなる。(メール認証API)', async () => { const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue(); usersRepositoryMockValue.findUserById = { @@ -286,41 +337,6 @@ describe('UsersService.confirmUser', () => { ), ); }); - it('管理者権限のあるアクセストークンを使用して、新規ユーザが追加される(role:None)', async () => { - const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue(); - const licensesRepositoryMockValue = null; - const adb2cParam = makeDefaultAdB2cMockValue(); - const sendgridMockValue = makeDefaultSendGridlValue(); - const configMockValue = makeDefaultConfigValue(); - const sortCriteriaRepositoryMockValue = - makeDefaultSortCriteriaRepositoryMockValue(); - const service = await makeUsersServiceMock( - usersRepositoryMockValue, - licensesRepositoryMockValue, - adb2cParam, - sendgridMockValue, - configMockValue, - sortCriteriaRepositoryMockValue, - ); - const name = 'test_user1'; - const role = USER_ROLES.NONE; - const email = 'test1@example.co.jp'; - const autoRenew = true; - const licenseAlert = true; - const notification = true; - const token: AccessToken = { userId: '0001', role: '', tier: 5 }; - expect( - await service.createUser( - token, - name, - role, - email, - autoRenew, - licenseAlert, - notification, - ), - ).toEqual(undefined); - }); }); describe('UsersService.createUser', () => { @@ -448,6 +464,43 @@ describe('UsersService.createUser', () => { ), ).toEqual(undefined); }); + + it('管理者権限のあるアクセストークンを使用して、新規ユーザが追加される(role:None)', async () => { + const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue(); + const licensesRepositoryMockValue = null; + const adb2cParam = makeDefaultAdB2cMockValue(); + const sendgridMockValue = makeDefaultSendGridlValue(); + const configMockValue = makeDefaultConfigValue(); + const sortCriteriaRepositoryMockValue = + makeDefaultSortCriteriaRepositoryMockValue(); + const service = await makeUsersServiceMock( + usersRepositoryMockValue, + licensesRepositoryMockValue, + adb2cParam, + sendgridMockValue, + configMockValue, + sortCriteriaRepositoryMockValue, + ); + const name = 'test_user1'; + const role = USER_ROLES.NONE; + const email = 'test1@example.co.jp'; + const autoRenew = true; + const licenseAlert = true; + const notification = true; + const token: AccessToken = { userId: '0001', role: '', tier: 5 }; + expect( + await service.createUser( + token, + name, + role, + email, + autoRenew, + licenseAlert, + notification, + ), + ).toEqual(undefined); + }); + it('DBネットワークエラーとなる場合、エラーとなる。', async () => { const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue(); const licensesRepositoryMockValue = null; @@ -1614,7 +1667,7 @@ describe('UsersService.updateUser', () => { true, ); - const { userId: user2 } = await createUser( + await createUser( source, accountId, 'external_id2', diff --git a/dictation_server/src/features/users/users.service.ts b/dictation_server/src/features/users/users.service.ts index 3e3752a..22cfc91 100644 --- a/dictation_server/src/features/users/users.service.ts +++ b/dictation_server/src/features/users/users.service.ts @@ -80,7 +80,9 @@ export class UsersService { try { // トランザクションで取得と更新をまとめる const userId = decodedToken.userId; - await this.usersRepository.updateUserVerified(userId); + await this.usersRepository.updateUserVerifiedAndCreateTrialLicense( + userId, + ); } catch (e) { this.logger.error(e); if (e instanceof Error) { diff --git a/dictation_server/src/repositories/licenses/licenses.repository.service.ts b/dictation_server/src/repositories/licenses/licenses.repository.service.ts index ab8bb6a..e2ebab0 100644 --- a/dictation_server/src/repositories/licenses/licenses.repository.service.ts +++ b/dictation_server/src/repositories/licenses/licenses.repository.service.ts @@ -97,6 +97,7 @@ export class LicensesRepositoryService { entityManager.getRepository(CardLicenseIssue); const licenses = []; + //TODO タスク 2409: カードライセンスのレコード作成がbulkinsertになっていない // ライセンステーブルを作成する(BULK INSERT) for (let i = 0; i < count; i++) { const license = new License(); @@ -153,6 +154,7 @@ export class LicensesRepositoryService { } const cardLicenses = []; + //TODO タスク 2409: カードライセンスのレコード作成がbulkinsertになっていない // カードライセンステーブルを作成する(BULK INSERT) for (let i = 0; i < count; i++) { const cardLicense = new CardLicense(); diff --git a/dictation_server/src/repositories/users/users.repository.service.ts b/dictation_server/src/repositories/users/users.repository.service.ts index 97a7417..04b8ed2 100644 --- a/dictation_server/src/repositories/users/users.repository.service.ts +++ b/dictation_server/src/repositories/users/users.repository.service.ts @@ -13,7 +13,15 @@ import { InvalidRoleChangeError, EncryptionPasswordNeedError, } from './errors/types'; -import { USER_ROLES } from '../../constants'; +import { + LICENSE_ALLOCATED_STATUS, + LICENSE_TYPE, + TRIAL_LICENSE_EXPIRATION_DAYS, + TRIAL_LICENSE_ISSUE_NUM, + USER_ROLES, +} from '../../constants'; +import { License } from '../licenses/entity/license.entity'; +import { ExpirationThresholdDate } from '../../features/licenses/types/types'; @Injectable() export class UsersRepositoryService { @@ -285,6 +293,69 @@ export class UsersRepositoryService { }); } + /** + * Emailを認証済みにして、トライアルライセンスを作成する + * @param id + * @returns user verified and create trial license + */ + async updateUserVerifiedAndCreateTrialLicense(id: number): Promise { + await this.dataSource.transaction(async (entityManager) => { + const userRepo = entityManager.getRepository(User); + const targetUser = await userRepo.findOne({ + relations: { + account: true, + }, + where: { + id: id, + }, + }); + + // 運用上ユーザがいないことはあり得ないが、プログラム上発生しうるのでエラーとして処理 + if (!targetUser) { + throw new UserNotFoundError(); + } + + if (targetUser.email_verified) { + throw new EmailAlreadyVerifiedError(); + } + + targetUser.email_verified = true; + + await userRepo.update({ id: targetUser.id }, targetUser); + + // トライアルライセンス100件を作成する + const licenseRepo = entityManager.getRepository(License); + const licenses: License[] = []; + const today = new Date(); + // トライアルライセンスの有効期限は今日を起算日として30日後の日付が変わるまで + const expiryDate = new ExpirationThresholdDate( + today.setDate(today.getDate() + TRIAL_LICENSE_EXPIRATION_DAYS), + ); + for (let i = 0; i < TRIAL_LICENSE_ISSUE_NUM; i++) { + const license = new License(); + license.expiry_date = expiryDate; + license.account_id = targetUser.account.id; + license.type = LICENSE_TYPE.TRIAL; + license.status = LICENSE_ALLOCATED_STATUS.UNALLOCATED; + licenses.push(license); + } + + await licenseRepo + .createQueryBuilder() + .insert() + .into(License) + .values( + licenses.map((value) => ({ + expiry_date: value.expiry_date, + account_id: value.account_id, + type: value.type, + status: value.status, + })), + ) + .execute(); + }); + } + /** * 同じアカウントIDを持つユーザーを探す * @param externalId