From 5b97b619668e0805c70882dcf852c3e46880bc56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B0=B4=E6=9C=AC=20=E7=A5=90=E5=B8=8C?= Date: Wed, 13 Dec 2023 02:04:16 +0000 Subject: [PATCH] =?UTF-8?q?Merged=20PR=20619:=20API=E4=BF=AE=E6=AD=A3?= =?UTF-8?q?=EF=BC=88License=20Inventory=E3=81=AE=E8=A8=88=E7=AE=97?= =?UTF-8?q?=E5=A4=89=E6=9B=B4=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 概要 [Task3270: API修正(License Inventoryの計算変更)](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/3270) - 何をどう変更したか、追加したライブラリなど License Inventoryの計算方法を変更 →割り当て済みライセンスは件数に含まれないようにする(未使用と再利用可能ライセンスのみ) ## レビューポイント 特になし ## 動作確認状況 - ローカルで確認、ユニットテスト ## 補足 LicenseSummaryのユニットテストが旧式であったため、新しい方式でテストを追加しました。 --- .../accounts/accounts.service.spec.ts | 290 ++++++------------ .../src/features/accounts/test/utility.ts | 3 +- .../accounts/accounts.repository.service.ts | 20 +- 3 files changed, 119 insertions(+), 194 deletions(-) diff --git a/dictation_server/src/features/accounts/accounts.service.spec.ts b/dictation_server/src/features/accounts/accounts.service.spec.ts index a21f1d6..023d046 100644 --- a/dictation_server/src/features/accounts/accounts.service.spec.ts +++ b/dictation_server/src/features/accounts/accounts.service.spec.ts @@ -1581,39 +1581,6 @@ describe('createPartnerAccount', () => { }); describe('AccountsService', () => { - it('アカウントに紐づくライセンス情報を取得する', async () => { - const accountId = 1; - const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue(); - const userGroupsRepositoryMockValue = - makeDefaultUserGroupsRepositoryMockValue(); - const adb2cParam = makeDefaultAdB2cMockValue(); - const accountsRepositoryMockValue = - makeDefaultAccountsRepositoryMockValue(); - const configMockValue = makeDefaultConfigValue(); - const sendGridMockValue = makeDefaultSendGridlValue(); - const blobStorageMockValue = makeBlobStorageServiceMockValue(); - const licensesRepositoryMockValue = - makeDefaultLicensesRepositoryMockValue(); - const worktypesRepositoryMockValue = - makeDefaultWorktypesRepositoryMockValue(); - - const service = await makeAccountsServiceMock( - accountsRepositoryMockValue, - usersRepositoryMockValue, - userGroupsRepositoryMockValue, - adb2cParam, - configMockValue, - sendGridMockValue, - blobStorageMockValue, - licensesRepositoryMockValue, - worktypesRepositoryMockValue, - ); - const context = makeContext(`uuidv4`, 'requestId'); - expect(await service.getLicenseSummary(context, accountId)).toEqual( - expectedAccountLisenceCounts, - ); - }); - it('ライセンス情報が取得できない場合、エラーとなる', async () => { const accountId = 1; const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue(); @@ -1861,21 +1828,7 @@ describe('AccountsService', () => { }); }); -const expectedAccountLisenceCounts = { - totalLicense: 1, - allocatedLicense: 2, - reusableLicense: 3, - freeLicense: 4, - expiringWithin14daysLicense: 5, - issueRequesting: 6, - numberOfRequesting: 7, - shortage: 0, - storageSize: 0, - usedSize: 0, - isStorageAvailable: false, -}; - -describe('getPartnerAccount', () => { +describe('getLicenseSummary', () => { let source: DataSource | null = null; beforeEach(async () => { source = new DataSource({ @@ -1893,173 +1846,132 @@ describe('getPartnerAccount', () => { await source.destroy(); source = null; }); - - it('パラメータのアカウント自身と子アカウントに紐つくライセンス情報を取得する', async () => { + it('第五階層のライセンス情報を取得する', async () => { if (!source) fail(); const module = await makeTestingModule(source); if (!module) fail(); - // 親アカウントと子アカウント2つ作成 + // 親アカウントと子アカウント2つ作成 const { id: parentAccountId } = ( await makeTestAccount(source, { parent_account_id: 0, - tier: 1, + tier: 4, company_name: 'PARENTCORP', }) ).account; - const { id: childAccountId1 } = ( await makeTestAccount(source, { parent_account_id: parentAccountId, - tier: 2, + tier: 5, company_name: 'CHILDCORP1', }) ).account; - const { id: childAccountId2 } = ( await makeTestAccount(source, { parent_account_id: parentAccountId, - tier: 2, + tier: 5, company_name: 'CHILDCORP2', }) ).account; - // 第二にリクエストを投げる用の第三を作成 - const { id: childAccountId3 } = ( - await makeTestAccount(source, { - parent_account_id: childAccountId1, - tier: 3, - company_name: 'CHILDCORP3', - }) - ).account; - const { id: childAccountId4 } = ( - await makeTestAccount(source, { - parent_account_id: childAccountId2, - tier: 3, - company_name: 'CHILDCORP4', - }) - ).account; + // 有効期限が14日後のライセンスを追加(5ライセンス) + const expiryDate = new Date(); + expiryDate.setDate(expiryDate.getDate() + 14); + expiryDate.setHours(23, 59, 59, 999); + for (let i = 0; i < 5; i++) { + await createLicenseSetExpiryDateAndStatus( + source, + childAccountId1, + expiryDate, + 'Allocated', + 1, + ); + await createLicenseSetExpiryDateAndStatus( + source, + childAccountId2, + expiryDate, + 'Allocated', + 1, + ); + } - // 所有ライセンスを追加(親:3、子1:1、子2:2) - await createLicense( - source, - 1, - null, - parentAccountId, - LICENSE_TYPE.NORMAL, - LICENSE_ALLOCATED_STATUS.UNALLOCATED, - null, - 1, - null, - null, - ); - await createLicense( - source, - 2, - null, - parentAccountId, - LICENSE_TYPE.NORMAL, - LICENSE_ALLOCATED_STATUS.UNALLOCATED, - null, - 1, - null, - null, - ); - await createLicense( - source, - 3, - null, - parentAccountId, - LICENSE_TYPE.NORMAL, - LICENSE_ALLOCATED_STATUS.UNALLOCATED, - null, - 1, - null, - null, - ); - await createLicense( - source, - 4, - null, - childAccountId1, - LICENSE_TYPE.NORMAL, - LICENSE_ALLOCATED_STATUS.UNALLOCATED, - null, - 2, - null, - null, - ); + // 有効期限が迫っていないライセンスを追加(子1:各ステータスのライセンスを1つずつ、計4つ) + const status = ['Unallocated', 'Allocated', 'Reusable', 'Deleted']; + status.forEach(async (element) => { + if (!source) fail(); + await createLicenseSetExpiryDateAndStatus( + source, + childAccountId1, + new Date(2500, 1, 1, 23, 59, 59), + element, + 1, + ); + }); - await createLicense( - source, - 5, - null, - childAccountId2, - LICENSE_TYPE.NORMAL, - LICENSE_ALLOCATED_STATUS.UNALLOCATED, - null, - 3, - null, - null, - ); - await createLicense( - source, - 6, - null, - childAccountId2, - LICENSE_TYPE.NORMAL, - LICENSE_ALLOCATED_STATUS.UNALLOCATED, - null, - 3, - null, - null, - ); + // 有効期限が迫っていないライセンスを追加(子2:Unallocatedを10件) + for (let i = 0; i < 10; i++) { + await createLicenseSetExpiryDateAndStatus( + source, + childAccountId2, + new Date(2500, 1, 1, 23, 59, 59), + 'Unallocated', + ); + } - // ライセンス注文を追加(子1→親:10ライセンス、子2→親:5ライセンス) - await createLicenseOrder( + // 有効期限未設定のライセンスを1件追加(子1) + await createLicenseSetExpiryDateAndStatus( source, childAccountId1, - parentAccountId, - 10, - 'TEST222', + null, + 'Unallocated', ); - await createLicenseOrder(source, childAccountId2, parentAccountId, 5); - - // ライセンス注文を追加(子3→子1:10ライセンス、子4→子2:10ライセンス) - await createLicenseOrder(source, childAccountId3, childAccountId1, 10); - await createLicenseOrder(source, childAccountId4, childAccountId2, 10); + // childAccountId1にallocatedLicenseを追加 + await createLicenseSetExpiryDateAndStatus( + source, + childAccountId1, + null, + 'Allocated', + 1, + ); + // childAccountId1からライセンスの注文を100件を追加 + await createLicenseOrder(source, childAccountId1, parentAccountId, 100); const service = module.get(AccountsService); - const accountId = parentAccountId; - const offset = 0; - const limit = 20; - - const context = makeContext(`uuidv4`, 'requestId'); - const response = await service.getPartnerLicenses( + const context = makeContext(`uuidv4`, 'xxx-xxx-xxx-xxx', 'requestId'); + const resultChild1 = await service.getLicenseSummary( context, - limit, - offset, - accountId, + childAccountId1, ); - - expect(response.total).toBe(2); - - expect(response.ownPartnerLicense.companyName).toBe('PARENTCORP'); - expect(response.ownPartnerLicense.tier).toBe(1); - expect(response.ownPartnerLicense.stockLicense).toBe(3); - expect(response.ownPartnerLicense.issuedRequested).toBe(15); - expect(response.ownPartnerLicense.shortage).toBe(12); - - expect(response.childrenPartnerLicenses[0].companyName).toBe('CHILDCORP1'); - expect(response.childrenPartnerLicenses[0].tier).toBe(2); - expect(response.childrenPartnerLicenses[0].stockLicense).toBe(1); - expect(response.childrenPartnerLicenses[0].issueRequesting).toBe(10); - expect(response.childrenPartnerLicenses[0].shortage).toBe(9); - - expect(response.childrenPartnerLicenses[1].companyName).toBe('CHILDCORP2'); - expect(response.childrenPartnerLicenses[1].tier).toBe(2); - expect(response.childrenPartnerLicenses[1].stockLicense).toBe(2); - expect(response.childrenPartnerLicenses[1].shortage).toBe(8); + const resultChild2 = await service.getLicenseSummary( + context, + childAccountId2, + ); + expect(resultChild1).toEqual({ + totalLicense: 3, + allocatedLicense: 7, + reusableLicense: 1, + freeLicense: 2, + expiringWithin14daysLicense: 5, + issueRequesting: 100, + numberOfRequesting: 1, + storageSize: 0, + usedSize: 0, + shortage: 2, + isStorageAvailable: false, + }); + expect(resultChild2).toEqual({ + totalLicense: 10, + allocatedLicense: 5, + reusableLicense: 0, + freeLicense: 10, + expiringWithin14daysLicense: 5, + issueRequesting: 0, + numberOfRequesting: 0, + storageSize: 0, + usedSize: 0, + shortage: 0, + isStorageAvailable: false, + }); }); }); @@ -2189,17 +2101,17 @@ describe('getPartnerAccount', () => { accountId, ); - // 有効期限間近(5件)+ 有効期限間近でない(3件)'Unallocated', 'Allocated', 'Reusable'+ 有効期限未設定(1件) → 9件 - expect(response.childrenPartnerLicenses[0].stockLicense).toBe(9); + // 有効期限間近(5件)+ 有効期限間近でない(3件)'Unallocated', 'Allocated', 'Reusable'+ 有効期限未設定(1件) → 3件 + expect(response.childrenPartnerLicenses[0].stockLicense).toBe(3); // 有効期限間近(5件) - {有効期限間近でない未割当(2件)'Unallocated', 'Reusable'+ 有効期限未設定(1件)} → 2件 expect(response.childrenPartnerLicenses[0].shortage).toBe(2); - // 有効期限間近(5件)+ 有効期限間近でない(10件) → 15件 - expect(response.childrenPartnerLicenses[1].stockLicense).toBe(15); + // 有効期限間近(5件)+ 有効期限間近でない(10件) → 10件 + expect(response.childrenPartnerLicenses[1].stockLicense).toBe(10); // 有効期限間近(5件)- (有効期限間近でない未割当(10件)'Unallocated' + 有効期限未設定(1件)) → -5件 → 0件 expect(response.childrenPartnerLicenses[1].shortage).toBe(0); - - expect(response.childrenPartnerLicenses[2].stockLicense).toBe(1); + // 有効期限が15日後のライセンス(1件)'Allocated' + expect(response.childrenPartnerLicenses[2].stockLicense).toBe(0); // 有効期限が15日後のものはshortageにカウントされない expect(response.childrenPartnerLicenses[2].shortage).toBe(0); }); @@ -6755,7 +6667,7 @@ describe('getCompanyName', () => { if (!module) fail(); const service = module.get(AccountsService); // 第五階層のアカウント作成 - const { account, admin } = await makeTestAccount(source, { + const { admin } = await makeTestAccount(source, { tier: 5, company_name: 'testCompany', }); diff --git a/dictation_server/src/features/accounts/test/utility.ts b/dictation_server/src/features/accounts/test/utility.ts index b52a186..e658d9b 100644 --- a/dictation_server/src/features/accounts/test/utility.ts +++ b/dictation_server/src/features/accounts/test/utility.ts @@ -56,13 +56,14 @@ export const createLicenseSetExpiryDateAndStatus = async ( accountId: number, expiryDate: Date | null, status: string, + allocated_user_id?: number | null, ): Promise => { const { identifiers } = await datasource.getRepository(License).insert({ expiry_date: expiryDate, account_id: accountId, type: 'NORMAL', status: status, - allocated_user_id: null, + allocated_user_id: allocated_user_id, order_id: null, deleted_at: null, delete_order_id: null, diff --git a/dictation_server/src/repositories/accounts/accounts.repository.service.ts b/dictation_server/src/repositories/accounts/accounts.repository.service.ts index bb124f7..872e22a 100644 --- a/dictation_server/src/repositories/accounts/accounts.repository.service.ts +++ b/dictation_server/src/repositories/accounts/accounts.repository.service.ts @@ -379,12 +379,18 @@ export class AccountsRepositoryService { { account_id: id, expiry_date: MoreThanOrEqual(currentDate), - status: Not(LICENSE_ALLOCATED_STATUS.DELETED), + status: In([ + LICENSE_ALLOCATED_STATUS.REUSABLE, + LICENSE_ALLOCATED_STATUS.UNALLOCATED, + ]), }, { account_id: id, expiry_date: IsNull(), - status: Not(LICENSE_ALLOCATED_STATUS.DELETED), + status: In([ + LICENSE_ALLOCATED_STATUS.REUSABLE, + LICENSE_ALLOCATED_STATUS.UNALLOCATED, + ]), }, ], comment: `${context.getTrackingId()}_${new Date().toUTCString()}`, @@ -530,12 +536,18 @@ export class AccountsRepositoryService { { account_id: id, expiry_date: MoreThanOrEqual(currentDate), - status: Not(LICENSE_ALLOCATED_STATUS.DELETED), + status: In([ + LICENSE_ALLOCATED_STATUS.REUSABLE, + LICENSE_ALLOCATED_STATUS.UNALLOCATED, + ]), }, { account_id: id, expiry_date: IsNull(), - status: Not(LICENSE_ALLOCATED_STATUS.DELETED), + status: In([ + LICENSE_ALLOCATED_STATUS.REUSABLE, + LICENSE_ALLOCATED_STATUS.UNALLOCATED, + ]), }, ], comment: `${context.getTrackingId()}_${new Date().toUTCString()}`,