diff --git a/dictation_server/db/migrations/036-add-account-id-column.sql b/dictation_server/db/migrations/036-add-account-id-column.sql new file mode 100644 index 0000000..37491e9 --- /dev/null +++ b/dictation_server/db/migrations/036-add-account-id-column.sql @@ -0,0 +1,5 @@ +-- +migrate Up +ALTER TABLE `license_allocation_history` ADD COLUMN `account_id` BIGINT UNSIGNED NOT NULL COMMENT 'アカウントID' AFTER `is_allocated`; + +-- +migrate Down +ALTER TABLE `license_allocation_history` DROP COLUMN `account_id`; \ No newline at end of file diff --git a/dictation_server/db/migrations/037-create_deleted_users.sql b/dictation_server/db/migrations/037-create_deleted_users.sql new file mode 100644 index 0000000..a3fa4ba --- /dev/null +++ b/dictation_server/db/migrations/037-create_deleted_users.sql @@ -0,0 +1,23 @@ +-- +migrate Up +CREATE TABLE IF NOT EXISTS `users_archive` ( + `id` BIGINT UNSIGNED NOT NULL PRIMARY KEY COMMENT 'ID', + `external_id` VARCHAR(255) NOT NULL COMMENT '外部ユーザーID', + `account_id` BIGINT UNSIGNED COMMENT 'アカウントID', + `role` VARCHAR(255) NOT NULL COMMENT '役職', + `author_id` VARCHAR(255) COMMENT 'AuthorID', + `accepted_terms_version` VARCHAR(255) NOT NULL COMMENT '同意済み利用規約バージョン', + `email_verified` BOOLEAN NOT NULL DEFAULT 0 COMMENT 'email認証が完了済みであるか', + `encryption` BOOLEAN DEFAULT FALSE NOT NULL COMMENT '音声ファイル暗号化するか', + `prompt` BOOLEAN DEFAULT FALSE NOT NULL COMMENT '録音時に強制的にWorkTypeIDの選択画面に遷移するか', + `deleted_at` TIMESTAMP COMMENT '削除時刻', + `created_by` VARCHAR(255) COMMENT '作成者', + `created_at` TIMESTAMP DEFAULT now() COMMENT '作成時刻', + `updated_by` VARCHAR(255) COMMENT '更新者', + `updated_at` TIMESTAMP DEFAULT now() COMMENT '更新時刻', + `auto_renew` BOOLEAN DEFAULT TRUE NOT NULL COMMENT 'ライセンスの自動更新をするかどうか', + `license_alert` BOOLEAN DEFAULT TRUE NOT NULL COMMENT 'ライセンスの期限切れ通知をするかどうか', + `notification` BOOLEAN DEFAULT TRUE NOT NULL COMMENT '完了通知をするかどうか' +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci; + +-- +migrate Down +DROP TABLE `users_archive`; \ No newline at end of file diff --git a/dictation_server/src/features/licenses/licenses.service.spec.ts b/dictation_server/src/features/licenses/licenses.service.spec.ts index 44dc8c8..4b5b87d 100644 --- a/dictation_server/src/features/licenses/licenses.service.spec.ts +++ b/dictation_server/src/features/licenses/licenses.service.spec.ts @@ -552,7 +552,14 @@ describe('ライセンス割り当て', () => { null, null, ); - await createLicenseAllocationHistory(source, 1, userId, 1, 'NONE'); + await createLicenseAllocationHistory( + source, + 1, + userId, + 1, + accountId, + 'NONE', + ); const service = module.get(UsersService); @@ -581,6 +588,9 @@ describe('ライセンス割り当て', () => { expect(licenseAllocationHistory.licenseAllocationHistory.is_allocated).toBe( true, ); + expect(licenseAllocationHistory.licenseAllocationHistory.account_id).toBe( + accountId, + ); }); it('再割り当て可能なライセンスに対して、ライセンス割り当てが完了する', async () => { @@ -607,7 +617,14 @@ describe('ライセンス割り当て', () => { null, null, ); - await createLicenseAllocationHistory(source, 1, userId, 1, 'NONE'); + await createLicenseAllocationHistory( + source, + 1, + userId, + 1, + accountId, + 'NONE', + ); const service = module.get(UsersService); @@ -630,6 +647,9 @@ describe('ライセンス割り当て', () => { expect(licenseAllocationHistory.licenseAllocationHistory.is_allocated).toBe( true, ); + expect(licenseAllocationHistory.licenseAllocationHistory.account_id).toBe( + accountId, + ); }); it('未割当のライセンスに対して、別のライセンスが割り当てられているユーザーの割り当てが完了する', async () => { @@ -668,7 +688,14 @@ describe('ライセンス割り当て', () => { null, null, ); - await createLicenseAllocationHistory(source, 1, userId, 1, 'NONE'); + await createLicenseAllocationHistory( + source, + 1, + userId, + 1, + accountId, + 'NONE', + ); const service = module.get(UsersService); @@ -695,6 +722,9 @@ describe('ライセンス割り当て', () => { expect(licenseAllocationHistory.licenseAllocationHistory.is_allocated).toBe( false, ); + expect(licenseAllocationHistory.licenseAllocationHistory.account_id).toBe( + accountId, + ); // 新たに割り当てたライセンスの状態確認 const result2 = await selectLicense(source, 2); @@ -717,6 +747,9 @@ describe('ライセンス割り当て', () => { expect( newlicenseAllocationHistory.licenseAllocationHistory.is_allocated, ).toBe(true); + expect( + newlicenseAllocationHistory.licenseAllocationHistory.account_id, + ).toBe(accountId); }); it('割り当て時にライセンス履歴テーブルへの登録が完了する(元がNORMALのとき)', async () => { @@ -755,7 +788,14 @@ describe('ライセンス割り当て', () => { null, null, ); - await createLicenseAllocationHistory(source, 1, userId, 1, 'NONE'); + await createLicenseAllocationHistory( + source, + 1, + userId, + 1, + accountId, + 'NONE', + ); const service = module.get(UsersService); await service.allocateLicense(makeContext('trackingId'), userId, 2); @@ -806,7 +846,14 @@ describe('ライセンス割り当て', () => { null, null, ); - await createLicenseAllocationHistory(source, 1, userId, 1, 'CARD'); + await createLicenseAllocationHistory( + source, + 1, + userId, + 1, + accountId, + 'CARD', + ); const service = module.get(UsersService); await service.allocateLicense(makeContext('trackingId'), userId, 2); @@ -857,7 +904,14 @@ describe('ライセンス割り当て', () => { null, null, ); - await createLicenseAllocationHistory(source, 1, userId, 1, 'TRIAL'); + await createLicenseAllocationHistory( + source, + 1, + userId, + 1, + accountId, + 'TRIAL', + ); const service = module.get(UsersService); await service.allocateLicense(makeContext('trackingId'), userId, 2); @@ -1000,7 +1054,14 @@ describe('ライセンス割り当て解除', () => { null, null, ); - await createLicenseAllocationHistory(source, 1, userId, 1, 'NONE'); + await createLicenseAllocationHistory( + source, + 1, + userId, + 1, + accountId, + 'NONE', + ); const service = module.get(UsersService); await service.deallocateLicense(makeContext('trackingId'), userId); @@ -1028,6 +1089,9 @@ describe('ライセンス割り当て解除', () => { expect(licenseAllocationHistory.licenseAllocationHistory.is_allocated).toBe( false, ); + expect(licenseAllocationHistory.licenseAllocationHistory.account_id).toBe( + accountId, + ); expect( licenseAllocationHistory.licenseAllocationHistory.switch_from_type, ).toBe('NONE'); @@ -1075,7 +1139,14 @@ describe('ライセンス割り当て解除', () => { null, null, ); - await createLicenseAllocationHistory(source, 1, userId, 1, 'NONE'); + await createLicenseAllocationHistory( + source, + 1, + userId, + 1, + accountId, + 'NONE', + ); const service = module.get(UsersService); await expect( diff --git a/dictation_server/src/features/licenses/test/utility.ts b/dictation_server/src/features/licenses/test/utility.ts index 7fe69a5..5a295e5 100644 --- a/dictation_server/src/features/licenses/test/utility.ts +++ b/dictation_server/src/features/licenses/test/utility.ts @@ -78,6 +78,7 @@ export const createLicenseAllocationHistory = async ( historyId: number, userId: number, licenseId: number, + accountId: number, type: string, ): Promise => { const { identifiers } = await datasource @@ -87,6 +88,7 @@ export const createLicenseAllocationHistory = async ( user_id: userId, license_id: licenseId, is_allocated: true, + account_id: accountId, executed_at: new Date(), switch_from_type: type, deleted_at: null, diff --git a/dictation_server/src/features/users/users.service.ts b/dictation_server/src/features/users/users.service.ts index 112140b..94377ca 100644 --- a/dictation_server/src/features/users/users.service.ts +++ b/dictation_server/src/features/users/users.service.ts @@ -892,7 +892,14 @@ export class UsersService { ); try { - await this.licensesRepository.allocateLicense(userId, newLicenseId); + const accountId = (await this.usersRepository.findUserById(userId)) + .account_id; + + await this.licensesRepository.allocateLicense( + userId, + newLicenseId, + accountId, + ); } catch (e) { this.logger.error(`error=${e}`); if (e instanceof Error) { @@ -933,7 +940,10 @@ export class UsersService { ); try { - await this.licensesRepository.deallocateLicense(userId); + const accountId = (await this.usersRepository.findUserById(userId)) + .account_id; + + await this.licensesRepository.deallocateLicense(userId, accountId); } catch (e) { this.logger.error(`error=${e}`); if (e instanceof Error) { diff --git a/dictation_server/src/repositories/licenses/entity/license.entity.ts b/dictation_server/src/repositories/licenses/entity/license.entity.ts index 88363ab..58716e5 100644 --- a/dictation_server/src/repositories/licenses/entity/license.entity.ts +++ b/dictation_server/src/repositories/licenses/entity/license.entity.ts @@ -160,6 +160,9 @@ export class LicenseAllocationHistory { @Column() is_allocated: boolean; + @Column() + account_id: number; + @Column() executed_at: Date; diff --git a/dictation_server/src/repositories/licenses/licenses.repository.service.ts b/dictation_server/src/repositories/licenses/licenses.repository.service.ts index a53dc7f..67496bf 100644 --- a/dictation_server/src/repositories/licenses/licenses.repository.service.ts +++ b/dictation_server/src/repositories/licenses/licenses.repository.service.ts @@ -452,7 +452,11 @@ export class LicensesRepositoryService { * @param userId * @param newLicenseId */ - async allocateLicense(userId: number, newLicenseId: number): Promise { + async allocateLicense( + userId: number, + newLicenseId: number, + accountId: number, + ): Promise { await this.dataSource.transaction(async (entityManager) => { const licenseRepo = entityManager.getRepository(License); const licenseAllocationHistoryRepo = entityManager.getRepository( @@ -503,6 +507,7 @@ export class LicensesRepositoryService { const deallocationHistory = new LicenseAllocationHistory(); deallocationHistory.user_id = userId; deallocationHistory.license_id = allocatedLicense.id; + deallocationHistory.account_id = accountId; deallocationHistory.is_allocated = false; deallocationHistory.executed_at = new Date(); deallocationHistory.switch_from_type = SWITCH_FROM_TYPE.NONE; @@ -548,6 +553,7 @@ export class LicensesRepositoryService { const allocationHistory = new LicenseAllocationHistory(); allocationHistory.user_id = userId; allocationHistory.license_id = targetLicense.id; + allocationHistory.account_id = accountId; allocationHistory.is_allocated = true; allocationHistory.executed_at = new Date(); // TODO switchFromTypeの値については「PBI1234: 第一階層として、ライセンス数推移情報をCSV出力したい」で正式対応 @@ -561,7 +567,7 @@ export class LicensesRepositoryService { * ユーザーに割り当てられているライセンスを解除する * @param userId */ - async deallocateLicense(userId: number): Promise { + async deallocateLicense(userId: number, accountId: number): Promise { await this.dataSource.transaction(async (entityManager) => { const licenseRepo = entityManager.getRepository(License); const licenseAllocationHistoryRepo = entityManager.getRepository( @@ -591,6 +597,7 @@ export class LicensesRepositoryService { const deallocationHistory = new LicenseAllocationHistory(); deallocationHistory.user_id = userId; deallocationHistory.license_id = allocatedLicense.id; + deallocationHistory.account_id = accountId; deallocationHistory.is_allocated = false; deallocationHistory.executed_at = new Date(); deallocationHistory.switch_from_type = SWITCH_FROM_TYPE.NONE;