From f0e0d5e6b18e2a2aa7dcd0dd248e8c6e1a0a5d89 Mon Sep 17 00:00:00 2001 From: "maruyama.t" Date: Mon, 19 Jun 2023 04:06:44 +0000 Subject: [PATCH] =?UTF-8?q?Merged=20PR=20162:=20API=20IF=E4=BF=AE=E6=AD=A3?= =?UTF-8?q?=EF=BC=88LicenseSummaryInfo=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 概要 [Task1961: API IF修正(LicenseSummaryInfo)](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/1961) - 何をどう変更したか、追加したライブラリなど API実装時に一時的にLicenseSummaryInfo2と命名していた定義を、LicenseSummaryInfoに修正。 それに伴い、既存のLicenseSummaryInfoはレスポンスに直接記載するよう修正。 openapi.jsonを再生成し、画面側のパラメータの取得の記載を修正。 - このPull Requestでの対象/対象外 storageSizeとusedSizeの取得はPBI対象外 - 影響範囲(他の機能にも影響があるか) なし ## レビューポイント - クライアント側に対する修正漏れがないか。 ## UIの変更 なし ## 動作確認状況 - ローカルでAPIの戻り値の確認と、画面にその値が表示されていることを確認。 ![image.png](https://dev.azure.com/ODMSCloud/6023ff7b-d41c-4fa7-9c6f-f576ba48c07c/_apis/git/repositories/302da463-a2d7-40f9-b2bb-6e8edf324fa9/pullRequests/162/attachments/image.png) ![image (2).png](https://dev.azure.com/ODMSCloud/6023ff7b-d41c-4fa7-9c6f-f576ba48c07c/_apis/git/repositories/302da463-a2d7-40f9-b2bb-6e8edf324fa9/pullRequests/162/attachments/image%20%282%29.png) ## 補足 - 相談、参考資料などがあれば --- dictation_client/src/api/api.ts | 476 ++++++++++++++---- .../licenseSummary/licenseSummarySlice.ts | 26 +- .../license/licenseSummary/operations.ts | 4 +- .../license/licenseSummary/selectors.ts | 2 +- .../features/license/licenseSummary/state.ts | 14 +- dictation_server/src/api/odms/openapi.json | 11 +- .../features/accounts/accounts.controller.ts | 8 +- .../accounts/accounts.service.spec.ts | 4 +- .../src/features/accounts/accounts.service.ts | 10 +- .../accounts/test/accounts.service.mock.ts | 27 +- .../src/features/accounts/types/types.ts | 26 +- .../accounts/accounts.repository.service.ts | 7 +- 12 files changed, 441 insertions(+), 174 deletions(-) diff --git a/dictation_client/src/api/api.ts b/dictation_client/src/api/api.ts index c445cee..2b0b5d9 100644 --- a/dictation_client/src/api/api.ts +++ b/dictation_client/src/api/api.ts @@ -49,6 +49,31 @@ export interface Account { */ 'accountId': number; } +/** + * + * @export + * @interface Assignee + */ +export interface Assignee { + /** + * TypistID(TypistIDかTypistGroupIDのどちらかに値が入る) + * @type {number} + * @memberof Assignee + */ + 'typistUserId'?: number; + /** + * TypistGroupID(TypistGroupIDかTypistIDのどちらかに値が入る) + * @type {number} + * @memberof Assignee + */ + 'typistGroupId'?: number; + /** + * Typist名 / TypistGroup名 + * @type {string} + * @memberof Assignee + */ + 'typistName': string; +} /** * * @export @@ -119,7 +144,7 @@ export interface AudioUploadFinishedRequest { */ 'fileName': string; /** - * 音声ファイルの録音時間(yyyy-mm-ddThh:mm:ss.sss) + * 音声ファイルの録音時間(ミリ秒の整数値) * @type {string} * @memberof AudioUploadFinishedRequest */ @@ -336,12 +361,72 @@ export interface GetLicenseSummaryRequest { * @interface GetLicenseSummaryResponse */ export interface GetLicenseSummaryResponse { - /** - * - * @type {LicenseSummaryInfo} - * @memberof GetLicenseSummaryResponse - */ - 'licenseSummaryInfo': LicenseSummaryInfo; + /** + * + * @type {LicenseSummaryInfo} + * @memberof GetLicenseSummaryResponse + */ + totalLicense: number; + /** + * + * @type {number} + * @memberof GetLicenseSummaryResponse + */ + allocatedLicense: number; + /** + * + * @type {number} + * @memberof GetLicenseSummaryResponse + */ + reusableLicense: number; + /** + * + * @type {number} + * @memberof GetLicenseSummaryResponse + */ + freeLicense: number; + /** + * + * @type {number} + * @memberof GetLicenseSummaryResponse + */ + expiringWithin14daysLicense: number; + /** + * + * @type {number} + * @memberof GetLicenseSummaryResponse + */ + issueRequesting: number; + /** + * + * @type {number} + * @memberof GetLicenseSummaryResponse + */ + numberOfRequesting: number; + /** + * + * @type {number} + * @memberof GetLicenseSummaryResponse + */ + shortage: number; + /** + * + * @type {number} + * @memberof GetLicenseSummaryResponse + */ + storageSize: number; + /** + * + * @type {number} + * @memberof GetLicenseSummaryResponse + */ + usedSize: number; + /** + * + * @type {boolean} + * @memberof GetLicenseSummaryResponse + */ + isAccountLock: boolean; } /** * @@ -430,6 +515,32 @@ export interface GetSortCriteriaResponse { */ 'paramName': string; } +/** + * + * @export + * @interface GetTypistGroupsResponse + */ +export interface GetTypistGroupsResponse { + /** + * + * @type {Array} + * @memberof GetTypistGroupsResponse + */ + 'typistGroups': Array; +} +/** + * + * @export + * @interface GetTypistsResponse + */ +export interface GetTypistsResponse { + /** + * + * @type {Array} + * @memberof GetTypistsResponse + */ + 'typists': Array; +} /** * * @export @@ -443,79 +554,6 @@ export interface GetUsersResponse { */ 'users': Array; } -/** - * - * @export - * @interface LicenseSummaryInfo - */ -export interface LicenseSummaryInfo { - /** - * - * @type {number} - * @memberof LicenseSummaryInfo - */ - 'totalLicense': number; - /** - * - * @type {number} - * @memberof LicenseSummaryInfo - */ - 'allocatedLicense': number; - /** - * - * @type {number} - * @memberof LicenseSummaryInfo - */ - 'reusableLicense': number; - /** - * - * @type {number} - * @memberof LicenseSummaryInfo - */ - 'freeLicense': number; - /** - * - * @type {number} - * @memberof LicenseSummaryInfo - */ - 'expiringWithin14daysLicense': number; - /** - * - * @type {number} - * @memberof LicenseSummaryInfo - */ - 'issueRequesting': number; - /** - * - * @type {number} - * @memberof LicenseSummaryInfo - */ - 'numberOfRequesting': number; - /** - * - * @type {number} - * @memberof LicenseSummaryInfo - */ - 'shortage': number; - /** - * - * @type {number} - * @memberof LicenseSummaryInfo - */ - 'storageSize': number; - /** - * - * @type {number} - * @memberof LicenseSummaryInfo - */ - 'usedSize': number; - /** - * - * @type {boolean} - * @memberof LicenseSummaryInfo - */ - 'isAccountLock': boolean; -} /** * * @export @@ -560,6 +598,19 @@ export interface OptionItemList { */ 'optionItemList': Array; } +/** + * + * @export + * @interface PostCheckoutPermissionRequest + */ +export interface PostCheckoutPermissionRequest { + /** + * 文字起こしに着手可能(チェックアウト可能)にしたい、グループ個人の一覧 + * @type {Array} + * @memberof PostCheckoutPermissionRequest + */ + 'assignees': Array; +} /** * * @export @@ -696,7 +747,7 @@ export interface Task { */ 'fileName': string; /** - * 音声ファイルの録音時間(yyyy-mm-ddThh:mm:ss.sss) + * 音声ファイルの録音時間(ミリ秒の整数値) * @type {string} * @memberof Task */ @@ -763,10 +814,10 @@ export interface Task { 'typist'?: TaskTypist; /** * 文字起こしに着手できる(チェックアウト可能な)、タスクにアサインされているグループ/個人の一覧 - * @type {Array} + * @type {Array} * @memberof Task */ - 'assignees': Array; + 'assignees': Array; /** * 音声ファイルのファイルステータス Uploaded / Pending / InProgress / Finished / Backup * @type {string} @@ -778,13 +829,13 @@ export interface Task { * @type {string} * @memberof Task */ - 'transcriptionStartedDate': string; + 'transcriptionStartedDate'?: string; /** * 文字起こし終了日時(yyyy-mm-ddThh:mm:ss.sss) * @type {string} * @memberof Task */ - 'transcriptionFinishedDate': string; + 'transcriptionFinishedDate'?: string; } /** * 割り当てられたユーザー @@ -793,23 +844,17 @@ export interface Task { */ export interface TaskTypist { /** - * TypistID(TypistIDかTypistGroupIDのどちらかに値が入る) + * TypistのユーザーID * @type {number} * @memberof TaskTypist */ - 'typistUserId'?: number; + 'id': number; /** - * TypistGroupID(TypistGroupIDかTypistIDのどちらかに値が入る) - * @type {number} - * @memberof TaskTypist - */ - 'typistGroupId'?: number; - /** - * Typist名 / TypistGroup名 + * Typistのユーザー名 * @type {string} * @memberof TaskTypist */ - 'typistName': string; + 'name': string; } /** * @@ -900,23 +945,36 @@ export interface TokenResponse { */ export interface Typist { /** - * TypistID(TypistIDかTypistGroupIDのどちらかに値が入る) + * TypistのユーザーID * @type {number} * @memberof Typist */ - 'typistUserId'?: number; + 'id': number; /** - * TypistGroupID(TypistGroupIDかTypistIDのどちらかに値が入る) - * @type {number} - * @memberof Typist - */ - 'typistGroupId'?: number; - /** - * Typist名 / TypistGroup名 + * Typistのユーザー名 * @type {string} * @memberof Typist */ - 'typistName': string; + 'name': string; +} +/** + * + * @export + * @interface TypistGroup + */ +export interface TypistGroup { + /** + * TypistGroupのID + * @type {number} + * @memberof TypistGroup + */ + 'id': number; + /** + * TypistGroup名 + * @type {string} + * @memberof TypistGroup + */ + 'name': string; } /** * @@ -1087,6 +1145,74 @@ export const AccountsApiAxiosParamCreator = function (configuration?: Configurat + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * ログインしているユーザーのアカウント配下のタイピストグループ一覧を取得します + * @summary + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getTypistGroups: async (options: AxiosRequestConfig = {}): Promise => { + const localVarPath = `/accounts/typist-groups`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication bearer required + // http bearer authentication required + await setBearerAuthToObject(localVarHeaderParameter, configuration) + + + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * ログインしているユーザーのアカウント配下のタイピスト一覧を取得します + * @summary + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getTypists: async (options: AxiosRequestConfig = {}): Promise => { + const localVarPath = `/accounts/typists`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication bearer required + // http bearer authentication required + await setBearerAuthToObject(localVarHeaderParameter, configuration) + + + setSearchParams(localVarUrlObj, localVarQueryParameter); let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; @@ -1138,6 +1264,26 @@ export const AccountsApiFp = function(configuration?: Configuration) { const localVarAxiosArgs = await localVarAxiosParamCreator.getMyAccount(options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, + /** + * ログインしているユーザーのアカウント配下のタイピストグループ一覧を取得します + * @summary + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async getTypistGroups(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.getTypistGroups(options); + return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + }, + /** + * ログインしているユーザーのアカウント配下のタイピスト一覧を取得します + * @summary + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async getTypists(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.getTypists(options); + return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + }, } }; @@ -1177,6 +1323,24 @@ export const AccountsApiFactory = function (configuration?: Configuration, baseP getMyAccount(options?: any): AxiosPromise { return localVarFp.getMyAccount(options).then((request) => request(axios, basePath)); }, + /** + * ログインしているユーザーのアカウント配下のタイピストグループ一覧を取得します + * @summary + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getTypistGroups(options?: any): AxiosPromise { + return localVarFp.getTypistGroups(options).then((request) => request(axios, basePath)); + }, + /** + * ログインしているユーザーのアカウント配下のタイピスト一覧を取得します + * @summary + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getTypists(options?: any): AxiosPromise { + return localVarFp.getTypists(options).then((request) => request(axios, basePath)); + }, }; }; @@ -1221,6 +1385,28 @@ export class AccountsApi extends BaseAPI { public getMyAccount(options?: AxiosRequestConfig) { return AccountsApiFp(this.configuration).getMyAccount(options).then((request) => request(this.axios, this.basePath)); } + + /** + * ログインしているユーザーのアカウント配下のタイピストグループ一覧を取得します + * @summary + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof AccountsApi + */ + public getTypistGroups(options?: AxiosRequestConfig) { + return AccountsApiFp(this.configuration).getTypistGroups(options).then((request) => request(this.axios, this.basePath)); + } + + /** + * ログインしているユーザーのアカウント配下のタイピスト一覧を取得します + * @summary + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof AccountsApi + */ + public getTypists(options?: AxiosRequestConfig) { + return AccountsApiFp(this.configuration).getTypists(options).then((request) => request(this.axios, this.basePath)); + } } @@ -2140,6 +2326,50 @@ export const TasksApiAxiosParamCreator = function (configuration?: Configuration options: localVarRequestOptions, }; }, + /** + * 指定した文字起こしタスクのチェックアウト候補を変更します。 + * @summary + * @param {number} audioFileId + * @param {PostCheckoutPermissionRequest} postCheckoutPermissionRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + changeCheckoutPermission: async (audioFileId: number, postCheckoutPermissionRequest: PostCheckoutPermissionRequest, options: AxiosRequestConfig = {}): Promise => { + // verify required parameter 'audioFileId' is not null or undefined + assertParamExists('changeCheckoutPermission', 'audioFileId', audioFileId) + // verify required parameter 'postCheckoutPermissionRequest' is not null or undefined + assertParamExists('changeCheckoutPermission', 'postCheckoutPermissionRequest', postCheckoutPermissionRequest) + const localVarPath = `/tasks/{audioFileId}/checkout-permission` + .replace(`{${"audioFileId"}}`, encodeURIComponent(String(audioFileId))); + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication bearer required + // http bearer authentication required + await setBearerAuthToObject(localVarHeaderParameter, configuration) + + + + localVarHeaderParameter['Content-Type'] = 'application/json'; + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + localVarRequestOptions.data = serializeDataIfNeeded(postCheckoutPermissionRequest, localVarRequestOptions, configuration) + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, /** * 指定した文字起こしタスクをチェックインします(ステータスをFinishedにします) * @summary @@ -2424,6 +2654,18 @@ export const TasksApiFp = function(configuration?: Configuration) { const localVarAxiosArgs = await localVarAxiosParamCreator.cancel(audioFileId, options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, + /** + * 指定した文字起こしタスクのチェックアウト候補を変更します。 + * @summary + * @param {number} audioFileId + * @param {PostCheckoutPermissionRequest} postCheckoutPermissionRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async changeCheckoutPermission(audioFileId: number, postCheckoutPermissionRequest: PostCheckoutPermissionRequest, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.changeCheckoutPermission(audioFileId, postCheckoutPermissionRequest, options); + return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + }, /** * 指定した文字起こしタスクをチェックインします(ステータスをFinishedにします) * @summary @@ -2524,6 +2766,17 @@ export const TasksApiFactory = function (configuration?: Configuration, basePath cancel(audioFileId: number, options?: any): AxiosPromise { return localVarFp.cancel(audioFileId, options).then((request) => request(axios, basePath)); }, + /** + * 指定した文字起こしタスクのチェックアウト候補を変更します。 + * @summary + * @param {number} audioFileId + * @param {PostCheckoutPermissionRequest} postCheckoutPermissionRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + changeCheckoutPermission(audioFileId: number, postCheckoutPermissionRequest: PostCheckoutPermissionRequest, options?: any): AxiosPromise { + return localVarFp.changeCheckoutPermission(audioFileId, postCheckoutPermissionRequest, options).then((request) => request(axios, basePath)); + }, /** * 指定した文字起こしタスクをチェックインします(ステータスをFinishedにします) * @summary @@ -2622,6 +2875,19 @@ export class TasksApi extends BaseAPI { return TasksApiFp(this.configuration).cancel(audioFileId, options).then((request) => request(this.axios, this.basePath)); } + /** + * 指定した文字起こしタスクのチェックアウト候補を変更します。 + * @summary + * @param {number} audioFileId + * @param {PostCheckoutPermissionRequest} postCheckoutPermissionRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof TasksApi + */ + public changeCheckoutPermission(audioFileId: number, postCheckoutPermissionRequest: PostCheckoutPermissionRequest, options?: AxiosRequestConfig) { + return TasksApiFp(this.configuration).changeCheckoutPermission(audioFileId, postCheckoutPermissionRequest, options).then((request) => request(this.axios, this.basePath)); + } + /** * 指定した文字起こしタスクをチェックインします(ステータスをFinishedにします) * @summary diff --git a/dictation_client/src/features/license/licenseSummary/licenseSummarySlice.ts b/dictation_client/src/features/license/licenseSummary/licenseSummarySlice.ts index 33e7511..2b5b746 100644 --- a/dictation_client/src/features/license/licenseSummary/licenseSummarySlice.ts +++ b/dictation_client/src/features/license/licenseSummary/licenseSummarySlice.ts @@ -4,19 +4,17 @@ import { getLicenseSummaryAsync } from "./operations"; const initialState: LicenseSummaryState = { domain: { - licenseSummaryInfo: { - totalLicense: 0, - allocatedLicense: 0, - reusableLicense: 0, - freeLicense: 0, - expiringWithin14daysLicense: 0, - issueRequesting: 0, - numberOfRequesting: 0, - shortage: 0, - storageSize: 0, - usedSize: 0, - isAccountLock: false, - }, + totalLicense: 0, + allocatedLicense: 0, + reusableLicense: 0, + freeLicense: 0, + expiringWithin14daysLicense: 0, + issueRequesting: 0, + numberOfRequesting: 0, + shortage: 0, + storageSize: 0, + usedSize: 0, + isAccountLock: false, }, }; @@ -30,7 +28,7 @@ export const licenseSummarySlice = createSlice({ }, extraReducers: (builder) => { builder.addCase(getLicenseSummaryAsync.fulfilled, (state, action) => { - state.domain.licenseSummaryInfo = action.payload.licenseSummaryInfo; + state.domain = action.payload; }); }, }); diff --git a/dictation_client/src/features/license/licenseSummary/operations.ts b/dictation_client/src/features/license/licenseSummary/operations.ts index 49cf8ad..1aa675a 100644 --- a/dictation_client/src/features/license/licenseSummary/operations.ts +++ b/dictation_client/src/features/license/licenseSummary/operations.ts @@ -39,9 +39,7 @@ export const getLicenseSummaryAsync = createAsyncThunk< headers: { authorization: `Bearer ${accessToken}` }, } ); - return { - licenseSummaryInfo: getLicenseSummaryResponse.data.licenseSummaryInfo, - }; + return getLicenseSummaryResponse.data; } catch (e) { // e ⇒ errorObjectに変換" const error = createErrorObject(e); diff --git a/dictation_client/src/features/license/licenseSummary/selectors.ts b/dictation_client/src/features/license/licenseSummary/selectors.ts index 8b3707f..e4eceee 100644 --- a/dictation_client/src/features/license/licenseSummary/selectors.ts +++ b/dictation_client/src/features/license/licenseSummary/selectors.ts @@ -2,4 +2,4 @@ import { RootState } from "app/store"; // 各値はそのまま画面に表示するので、licenseSummaryInfoとして値を取得する export const selecLicenseSummaryInfo = (state: RootState) => - state.licenseSummary.domain.licenseSummaryInfo; + state.licenseSummary.domain; diff --git a/dictation_client/src/features/license/licenseSummary/state.ts b/dictation_client/src/features/license/licenseSummary/state.ts index b56743e..d7145e6 100644 --- a/dictation_client/src/features/license/licenseSummary/state.ts +++ b/dictation_client/src/features/license/licenseSummary/state.ts @@ -1,9 +1,17 @@ -import { LicenseSummaryInfo } from "../../../api/api"; - export interface LicenseSummaryState { domain: Domain; } export interface Domain { - licenseSummaryInfo: LicenseSummaryInfo; + totalLicense: number; + allocatedLicense: number; + reusableLicense: number; + freeLicense: number; + expiringWithin14daysLicense: number; + issueRequesting: number; + numberOfRequesting: number; + shortage: number; + storageSize: number; + usedSize: number; + isAccountLock: boolean; } diff --git a/dictation_server/src/api/odms/openapi.json b/dictation_server/src/api/odms/openapi.json index 9a5c27a..ec1db17 100644 --- a/dictation_server/src/api/odms/openapi.json +++ b/dictation_server/src/api/odms/openapi.json @@ -1956,7 +1956,7 @@ }, "required": ["accountId"] }, - "LicenseSummaryInfo": { + "GetLicenseSummaryResponse": { "type": "object", "properties": { "totalLicense": { @@ -2007,15 +2007,6 @@ "isAccountLock" ] }, - "GetLicenseSummaryResponse": { - "type": "object", - "properties": { - "licenseSummaryInfo": { - "$ref": "#/components/schemas/LicenseSummaryInfo" - } - }, - "required": ["licenseSummaryInfo"] - }, "Account": { "type": "object", "properties": { diff --git a/dictation_server/src/features/accounts/accounts.controller.ts b/dictation_server/src/features/accounts/accounts.controller.ts index 0e5e68e..a23e3af 100644 --- a/dictation_server/src/features/accounts/accounts.controller.ts +++ b/dictation_server/src/features/accounts/accounts.controller.ts @@ -119,10 +119,10 @@ export class AccountsController { console.log(req.header('Authorization')); console.log(body); - const info = await this.accountService.getLicenseSummary(body.accountId); - return { - licenseSummaryInfo: info, - }; + const response = await this.accountService.getLicenseSummary( + body.accountId, + ); + return response; } @ApiResponse({ diff --git a/dictation_server/src/features/accounts/accounts.service.spec.ts b/dictation_server/src/features/accounts/accounts.service.spec.ts index 343b6a2..f845411 100644 --- a/dictation_server/src/features/accounts/accounts.service.spec.ts +++ b/dictation_server/src/features/accounts/accounts.service.spec.ts @@ -32,7 +32,7 @@ it('ライセンス情報が取得できない場合、エラーとなる', asyn const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue(); const adb2cParam = makeDefaultAdB2cMockValue(); const accountsRepositoryMockValue = makeDefaultAccountsRepositoryMockValue(); - accountsRepositoryMockValue.getLicenseSummaryInfo = new Error('DB error'); + accountsRepositoryMockValue.getLicenseSummaryInfo = null; const sendGridMockValue = makeDefaultSendGridlValue(); const service = await makeAccountsServiceMock( accountsRepositoryMockValue, @@ -56,7 +56,7 @@ const expectedAccountLisenceCounts = { expiringWithin14daysLicense: 5, issueRequesting: 6, numberOfRequesting: 7, - shortage: 3, + shortage: 0, storageSize: 0, usedSize: 0, isAccountLock: false, diff --git a/dictation_server/src/features/accounts/accounts.service.ts b/dictation_server/src/features/accounts/accounts.service.ts index 1a8ee60..9ee99d5 100644 --- a/dictation_server/src/features/accounts/accounts.service.ts +++ b/dictation_server/src/features/accounts/accounts.service.ts @@ -15,7 +15,7 @@ import { Account } from '../../repositories/accounts/entity/account.entity'; import { User } from '../../repositories/users/entity/user.entity'; import { LICENSE_EXPIRATION_THRESHOLD_DAYS, TIER_5 } from '../../constants'; import { makeErrorResponse } from '../../common/error/makeErrorResponse'; -import { LicenseSummaryInfo } from './types/types'; +import { GetLicenseSummaryResponse } from './types/types'; import { AccessToken } from '../../common/token'; @Injectable() @@ -33,7 +33,9 @@ export class AccountsService { * @param accountId * @returns LicenseSummary */ - async getLicenseSummary(accountId: number): Promise { + async getLicenseSummary( + accountId: number, + ): Promise { this.logger.log(`[IN] ${this.getLicenseSummary.name}`); try { @@ -69,7 +71,7 @@ export class AccountsService { let shortage = allocatableLicenseWithMargin - expiringSoonLicense; shortage = shortage >= 0 ? 0 : Math.abs(shortage); - const licenseSummaryInfo: LicenseSummaryInfo = { + const licenseSummaryResponse: GetLicenseSummaryResponse = { totalLicense, allocatedLicense, reusableLicense, @@ -82,7 +84,7 @@ export class AccountsService { shortage, isAccountLock, }; - return licenseSummaryInfo; + return licenseSummaryResponse; } catch (e) { console.log(e); console.log('get licenseSummary failed'); diff --git a/dictation_server/src/features/accounts/test/accounts.service.mock.ts b/dictation_server/src/features/accounts/test/accounts.service.mock.ts index b540be5..36bc170 100644 --- a/dictation_server/src/features/accounts/test/accounts.service.mock.ts +++ b/dictation_server/src/features/accounts/test/accounts.service.mock.ts @@ -26,7 +26,10 @@ export type SendGridMockValue = { sendMail: undefined | Error; }; export type AccountsRepositoryMockValue = { - getLicenseSummaryInfo: LicenseSummaryInfo | Error; + getLicenseSummaryInfo: { + licenseSummary: LicenseSummaryInfo; + isAccountLock: boolean; + }; }; export const makeAccountsServiceMock = async ( accountsRepositoryMockValue: AccountsRepositoryMockValue, @@ -69,7 +72,13 @@ export const makeAccountsRepositoryMock = ( getLicenseSummaryInfo instanceof Error ? jest.fn, []>().mockRejectedValue(getLicenseSummaryInfo) : jest - .fn, []>() + .fn< + Promise<{ + licenseSummary: LicenseSummaryInfo; + isAccountLock: boolean; + }>, + [] + >() .mockResolvedValue(getLicenseSummaryInfo), }; }; @@ -121,15 +130,17 @@ export const makeDefaultAccountsRepositoryMockValue = allocatedLicense: 2, reusableLicense: 3, freeLicense: 4, - expiringWithin14daysLicense: 5, + expiringSoonLicense: 5, issueRequesting: 6, numberOfRequesting: 7, - shortage: 8, - storageSize: 0, - usedSize: 0, - isAccountLock: false, + allocatableLicenseWithMargin: 8, + }; + return { + getLicenseSummaryInfo: { + licenseSummary: licenseSummaryInfo, + isAccountLock: false, + }, }; - return { getLicenseSummaryInfo: licenseSummaryInfo }; }; export const makeDefaultUsersRepositoryMockValue = (): UsersRepositoryMockValue => { diff --git a/dictation_server/src/features/accounts/types/types.ts b/dictation_server/src/features/accounts/types/types.ts index de138dd..90fa518 100644 --- a/dictation_server/src/features/accounts/types/types.ts +++ b/dictation_server/src/features/accounts/types/types.ts @@ -33,8 +33,17 @@ export class GetLicenseSummaryRequest { @ApiProperty() accountId: number; } -// XXX Task1961で直す、レスポンス内に直接定義する export class LicenseSummaryInfo { + totalLicense: number; + allocatedLicense: number; + reusableLicense: number; + freeLicense: number; + expiringSoonLicense: number; + issueRequesting: number; + numberOfRequesting: number; + allocatableLicenseWithMargin: number; +} +export class GetLicenseSummaryResponse { @ApiProperty() totalLicense: number; @@ -68,21 +77,6 @@ export class LicenseSummaryInfo { @ApiProperty() isAccountLock: boolean; } -// XXX Task1961で直すLicenseSummaryInfo2→LicenseSummaryInfo -export class LicenseSummaryInfo2 { - totalLicense: number; - allocatedLicense: number; - reusableLicense: number; - freeLicense: number; - expiringSoonLicense: number; - issueRequesting: number; - numberOfRequesting: number; - allocatableLicenseWithMargin: number; -} -export class GetLicenseSummaryResponse { - @ApiProperty({ type: LicenseSummaryInfo }) - licenseSummaryInfo: LicenseSummaryInfo; -} export class Account { @ApiProperty() diff --git a/dictation_server/src/repositories/accounts/accounts.repository.service.ts b/dictation_server/src/repositories/accounts/accounts.repository.service.ts index 2ce3c01..f61a367 100644 --- a/dictation_server/src/repositories/accounts/accounts.repository.service.ts +++ b/dictation_server/src/repositories/accounts/accounts.repository.service.ts @@ -21,7 +21,7 @@ import { LICENSE_ALLOCATED_STATUS, LICENSE_STATUS_ISSUE_REQUESTING, } from '../../constants'; -import { LicenseSummaryInfo2 } from '../../features/accounts/types/types'; +import { LicenseSummaryInfo } from '../../features/accounts/types/types'; export class AccountNotFoundError extends Error {} @@ -171,12 +171,11 @@ export class AccountsRepositoryService { * @param expiringSoonDate * @returns licenseSummary */ - // XXX Task1961で直すLicenseSummaryInfo2→LicenseSummaryInfo async getLicenseSummaryInfo( id: number, currentDate: Date, expiringSoonDate: Date, - ): Promise<{ licenseSummary: LicenseSummaryInfo2; isAccountLock: boolean }> { + ): Promise<{ licenseSummary: LicenseSummaryInfo; isAccountLock: boolean }> { return await this.dataSource.transaction(async (entityManager) => { const license = entityManager.getRepository(License); const licenseOrder = entityManager.getRepository(LicenseOrder); @@ -275,7 +274,7 @@ export class AccountsRepositoryService { // アカウントのロック状態を取得する const isAccountLock = (await this.findAccountById(id)).locked; - let licenseSummary = new LicenseSummaryInfo2(); + let licenseSummary = new LicenseSummaryInfo(); licenseSummary = { totalLicense: totalLicense, allocatedLicense: allocatedLicense,