diff --git a/dictation_client/src/AppRouter.tsx b/dictation_client/src/AppRouter.tsx index 048d72e..08b7185 100644 --- a/dictation_client/src/AppRouter.tsx +++ b/dictation_client/src/AppRouter.tsx @@ -16,6 +16,8 @@ import UserListPage from "pages/UserListPage"; import LicensePage from "pages/LicensePage"; import DictationPage from "pages/DictationPage"; import PartnerPage from "pages/PartnerPage"; +import WorkflowPage from "pages/WorkflowPage"; +import TypistGroupSettingPage from "pages/TypistGroupSettingPage"; const AppRouter: React.FC = () => ( @@ -58,7 +60,11 @@ const AppRouter: React.FC = () => ( /> } />} + element={} />} + /> + } />} /> } - * @memberof AudioUploadFinishedRequest - */ - 'optionItemList': Array; - /** - * - * @type {boolean} - * @memberof AudioUploadFinishedRequest - */ - 'isEncrypted': boolean; + /** + * アップロード先Blob Storage(ファイル名含む) + * @type {string} + * @memberof AudioUploadFinishedRequest + */ + url: string; + /** + * 自分自身(ログイン認証)したAuthorID + * @type {string} + * @memberof AudioUploadFinishedRequest + */ + authorId: string; + /** + * 音声ファイル名 + * @type {string} + * @memberof AudioUploadFinishedRequest + */ + fileName: string; + /** + * 音声ファイルの録音時間(ミリ秒の整数値) + * @type {string} + * @memberof AudioUploadFinishedRequest + */ + duration: string; + /** + * 音声ファイルの録音作成日時(開始日時)(yyyy-mm-ddThh:mm:ss.sss) + * @type {string} + * @memberof AudioUploadFinishedRequest + */ + createdDate: string; + /** + * 音声ファイルの録音作成終了日時(yyyy-mm-ddThh:mm:ss.sss) + * @type {string} + * @memberof AudioUploadFinishedRequest + */ + finishedDate: string; + /** + * 音声ファイルのアップロード日時(yyyy-mm-ddThh:mm:ss.sss) + * @type {string} + * @memberof AudioUploadFinishedRequest + */ + uploadedDate: string; + /** + * 音声ファイルのファイルサイズ(Byte) + * @type {number} + * @memberof AudioUploadFinishedRequest + */ + fileSize: number; + /** + * 優先度 \"00\":Normal / \"01\":High + * @type {string} + * @memberof AudioUploadFinishedRequest + */ + priority: string; + /** + * 録音形式: DSS/DS2(SP)/DS2(QP) + * @type {string} + * @memberof AudioUploadFinishedRequest + */ + audioFormat: string; + /** + * + * @type {string} + * @memberof AudioUploadFinishedRequest + */ + comment: string; + /** + * + * @type {string} + * @memberof AudioUploadFinishedRequest + */ + workType: string; + /** + * 音声ファイルに紐づくOption Itemの一覧(10個固定) + * @type {Array} + * @memberof AudioUploadFinishedRequest + */ + optionItemList: Array; + /** + * + * @type {boolean} + * @memberof AudioUploadFinishedRequest + */ + isEncrypted: boolean; } /** - * + * * @export * @interface AudioUploadFinishedResponse */ export interface AudioUploadFinishedResponse { - /** - * 8桁固定の数字 - * @type {string} - * @memberof AudioUploadFinishedResponse - */ - 'jobNumber': string; + /** + * 8桁固定の数字 + * @type {string} + * @memberof AudioUploadFinishedResponse + */ + jobNumber: string; } /** - * + * * @export * @interface AudioUploadLocationResponse */ export interface AudioUploadLocationResponse { - /** - * Blob StorageにアクセスするためのSASトークン入りのアクセスURL - * @type {string} - * @memberof AudioUploadLocationResponse - */ - 'url': string; + /** + * Blob StorageにアクセスするためのSASトークン入りのアクセスURL + * @type {string} + * @memberof AudioUploadLocationResponse + */ + url: string; } /** - * + * * @export * @interface ConfirmRequest */ export interface ConfirmRequest { - /** - * - * @type {string} - * @memberof ConfirmRequest - */ - 'token': string; + /** + * + * @type {string} + * @memberof ConfirmRequest + */ + token: string; } /** - * + * * @export * @interface CreateAccountRequest */ export interface CreateAccountRequest { - /** - * - * @type {string} - * @memberof CreateAccountRequest - */ - 'companyName': string; - /** - * 国名(ISO 3166-1 alpha-2) - * @type {string} - * @memberof CreateAccountRequest - */ - 'country': string; - /** - * - * @type {number} - * @memberof CreateAccountRequest - */ - 'dealerAccountId': number | null; - /** - * - * @type {string} - * @memberof CreateAccountRequest - */ - 'adminName': string; - /** - * - * @type {string} - * @memberof CreateAccountRequest - */ - 'adminMail': string; - /** - * - * @type {string} - * @memberof CreateAccountRequest - */ - 'adminPassword': string; - /** - * 同意済み利用規約のバージョン - * @type {string} - * @memberof CreateAccountRequest - */ - 'acceptedTermsVersion': string; - /** - * reCAPTCHA Token - * @type {string} - * @memberof CreateAccountRequest - */ - 'token': string; + /** + * + * @type {string} + * @memberof CreateAccountRequest + */ + companyName: string; + /** + * 国名(ISO 3166-1 alpha-2) + * @type {string} + * @memberof CreateAccountRequest + */ + country: string; + /** + * + * @type {number} + * @memberof CreateAccountRequest + */ + dealerAccountId?: number; + /** + * + * @type {string} + * @memberof CreateAccountRequest + */ + adminName: string; + /** + * + * @type {string} + * @memberof CreateAccountRequest + */ + adminMail: string; + /** + * + * @type {string} + * @memberof CreateAccountRequest + */ + adminPassword: string; + /** + * 同意済み利用規約のバージョン + * @type {string} + * @memberof CreateAccountRequest + */ + acceptedTermsVersion: string; + /** + * reCAPTCHA Token + * @type {string} + * @memberof CreateAccountRequest + */ + token: string; } /** - * + * * @export * @interface CreateOrdersRequest */ export interface CreateOrdersRequest { - /** - * - * @type {string} - * @memberof CreateOrdersRequest - */ - 'poNumber': string; - /** - * - * @type {number} - * @memberof CreateOrdersRequest - */ - 'orderCount': number; + /** + * + * @type {string} + * @memberof CreateOrdersRequest + */ + poNumber: string; + /** + * + * @type {number} + * @memberof CreateOrdersRequest + */ + orderCount: number; } /** - * + * * @export * @interface CreatePartnerAccountRequest */ export interface CreatePartnerAccountRequest { - /** - * - * @type {string} - * @memberof CreatePartnerAccountRequest - */ - 'companyName': string; - /** - * 国名(ISO 3166-1 alpha-2) - * @type {string} - * @memberof CreatePartnerAccountRequest - */ - 'country': string; - /** - * - * @type {string} - * @memberof CreatePartnerAccountRequest - */ - 'adminName': string; - /** - * - * @type {string} - * @memberof CreatePartnerAccountRequest - */ - 'email': string; + /** + * + * @type {string} + * @memberof CreatePartnerAccountRequest + */ + companyName: string; + /** + * 国名(ISO 3166-1 alpha-2) + * @type {string} + * @memberof CreatePartnerAccountRequest + */ + country: string; + /** + * + * @type {string} + * @memberof CreatePartnerAccountRequest + */ + adminName: string; + /** + * + * @type {string} + * @memberof CreatePartnerAccountRequest + */ + email: string; } /** - * + * + * @export + * @interface Dealer + */ +export interface Dealer { + /** + * アカウントID + * @type {number} + * @memberof Dealer + */ + id: number; + /** + * 会社名 + * @type {string} + * @memberof Dealer + */ + name: string; + /** + * 国名(ISO 3166-1 alpha-2) + * @type {string} + * @memberof Dealer + */ + country: string; +} +/** + * * @export * @interface ErrorResponse */ export interface ErrorResponse { - /** - * - * @type {string} - * @memberof ErrorResponse - */ - 'message': string; - /** - * - * @type {string} - * @memberof ErrorResponse - */ - 'code': string; + /** + * + * @type {string} + * @memberof ErrorResponse + */ + message: string; + /** + * + * @type {string} + * @memberof ErrorResponse + */ + code: string; } /** - * + * + * @export + * @interface GetAllocatableLicensesResponse + */ +export interface GetAllocatableLicensesResponse { + /** + * + * @type {Array} + * @memberof GetAllocatableLicensesResponse + */ + allocatableLicenses: Array; +} +/** + * + * @export + * @interface GetDealersResponse + */ +export interface GetDealersResponse { + /** + * + * @type {Array} + * @memberof GetDealersResponse + */ + dealers: Array; +} +/** + * * @export * @interface GetLicenseSummaryRequest */ export interface GetLicenseSummaryRequest { - /** - * - * @type {number} - * @memberof GetLicenseSummaryRequest - */ - 'accountId': number; + /** + * + * @type {number} + * @memberof GetLicenseSummaryRequest + */ + accountId: number; } /** - * + * * @export * @interface GetLicenseSummaryResponse */ export interface GetLicenseSummaryResponse { - /** - * - * @type {number} - * @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 - */ - 'isStorageAvailable': boolean; + /** + * + * @type {number} + * @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 + */ + isStorageAvailable: boolean; } /** - * + * * @export * @interface GetMyAccountResponse */ export interface GetMyAccountResponse { - /** - * - * @type {Account} - * @memberof GetMyAccountResponse - */ - 'account': Account; + /** + * + * @type {Account} + * @memberof GetMyAccountResponse + */ + account: Account; } /** - * + * * @export * @interface GetOrderHistoriesRequest */ export interface GetOrderHistoriesRequest { - /** - * 取得件数 - * @type {number} - * @memberof GetOrderHistoriesRequest - */ - 'limit': number; - /** - * 開始位置 - * @type {number} - * @memberof GetOrderHistoriesRequest - */ - 'offset': number; - /** - * アカウントID - * @type {number} - * @memberof GetOrderHistoriesRequest - */ - 'accountId': number; + /** + * 取得件数 + * @type {number} + * @memberof GetOrderHistoriesRequest + */ + limit: number; + /** + * 開始位置 + * @type {number} + * @memberof GetOrderHistoriesRequest + */ + offset: number; + /** + * アカウントID + * @type {number} + * @memberof GetOrderHistoriesRequest + */ + accountId: number; } /** - * + * * @export * @interface GetOrderHistoriesResponse */ export interface GetOrderHistoriesResponse { - /** - * 合計件数 - * @type {number} - * @memberof GetOrderHistoriesResponse - */ - 'total': number; - /** - * - * @type {Array} - * @memberof GetOrderHistoriesResponse - */ - 'orderHistories': Array; + /** + * 合計件数 + * @type {number} + * @memberof GetOrderHistoriesResponse + */ + total: number; + /** + * + * @type {Array} + * @memberof GetOrderHistoriesResponse + */ + orderHistories: Array; } /** - * + * * @export * @interface GetPartnerLicensesRequest */ export interface GetPartnerLicensesRequest { - /** - * - * @type {number} - * @memberof GetPartnerLicensesRequest - */ - 'limit': number; - /** - * - * @type {number} - * @memberof GetPartnerLicensesRequest - */ - 'offset': number; - /** - * - * @type {number} - * @memberof GetPartnerLicensesRequest - */ - 'accountId': number; + /** + * + * @type {number} + * @memberof GetPartnerLicensesRequest + */ + limit: number; + /** + * + * @type {number} + * @memberof GetPartnerLicensesRequest + */ + offset: number; + /** + * + * @type {number} + * @memberof GetPartnerLicensesRequest + */ + accountId: number; } /** - * + * * @export * @interface GetPartnerLicensesResponse */ export interface GetPartnerLicensesResponse { - /** - * - * @type {number} - * @memberof GetPartnerLicensesResponse - */ - 'total': number; - /** - * - * @type {PartnerLicenseInfo} - * @memberof GetPartnerLicensesResponse - */ - 'ownPartnerLicense': PartnerLicenseInfo; - /** - * - * @type {Array} - * @memberof GetPartnerLicensesResponse - */ - 'childrenPartnerLicenses': Array; + /** + * + * @type {number} + * @memberof GetPartnerLicensesResponse + */ + total: number; + /** + * + * @type {PartnerLicenseInfo} + * @memberof GetPartnerLicensesResponse + */ + ownPartnerLicense: PartnerLicenseInfo; + /** + * + * @type {Array} + * @memberof GetPartnerLicensesResponse + */ + childrenPartnerLicenses: Array; } /** - * + * * @export * @interface GetRelationsResponse */ export interface GetRelationsResponse { - /** - * ログインしたユーザーのAuthorID(Authorでない場合は空文字) - * @type {string} - * @memberof GetRelationsResponse - */ - 'authorId': string; - /** - * 属しているアカウントのAuthorID List(全て) - * @type {Array} - * @memberof GetRelationsResponse - */ - 'authorIdList': Array; - /** - * アカウントに設定されているWorktypeIDのリスト(最大20個) - * @type {Array} - * @memberof GetRelationsResponse - */ - 'workTypeList': Array; - /** - * ユーザーが音声ファイルを暗号化するかどうか - * @type {boolean} - * @memberof GetRelationsResponse - */ - 'isEncrypted': boolean; - /** - * ユーザーが暗号化を掛ける場合のパスワード - * @type {string} - * @memberof GetRelationsResponse - */ - 'encryptionPassword': string | null; - /** - * アカウントがデフォルトで利用するWorkTypeID(アカウントに紐づくWorkTypeIDから一つ指定) - * @type {string} - * @memberof GetRelationsResponse - */ - 'activeWorktype': string; - /** - * 録音形式: DSS/DS2(SP)/DS2(QP): DS2固定 - * @type {string} - * @memberof GetRelationsResponse - */ - 'audioFormat': string; - /** - * デバイス上で自動的にWorkTypeの選択画面を表示するかどうかのユーザーごとの設定(Authorでない場合はfalse) - * @type {boolean} - * @memberof GetRelationsResponse - */ - 'prompt': boolean; + /** + * ログインしたユーザーのAuthorID(Authorでない場合は空文字) + * @type {string} + * @memberof GetRelationsResponse + */ + authorId: string; + /** + * 属しているアカウントのAuthorID List(全て) + * @type {Array} + * @memberof GetRelationsResponse + */ + authorIdList: Array; + /** + * アカウントに設定されているWorktypeIDのリスト(最大20個) + * @type {Array} + * @memberof GetRelationsResponse + */ + workTypeList: Array; + /** + * ユーザーが音声ファイルを暗号化するかどうか + * @type {boolean} + * @memberof GetRelationsResponse + */ + isEncrypted: boolean; + /** + * ユーザーが暗号化を掛ける場合のパスワード + * @type {string} + * @memberof GetRelationsResponse + */ + encryptionPassword: string | null; + /** + * アカウントがデフォルトで利用するWorkTypeID(アカウントに紐づくWorkTypeIDから一つ指定) + * @type {string} + * @memberof GetRelationsResponse + */ + activeWorktype: string; + /** + * 録音形式: DSS/DS2(SP)/DS2(QP): DS2固定 + * @type {string} + * @memberof GetRelationsResponse + */ + audioFormat: string; + /** + * デバイス上で自動的にWorkTypeの選択画面を表示するかどうかのユーザーごとの設定(Authorでない場合はfalse) + * @type {boolean} + * @memberof GetRelationsResponse + */ + prompt: boolean; } /** - * + * * @export * @interface GetSortCriteriaResponse */ export interface GetSortCriteriaResponse { - /** - * ASC/DESC - * @type {string} - * @memberof GetSortCriteriaResponse - */ - 'direction': string; - /** - * JOB_NUMBER/STATUS/ENCRYPTION/AUTHOR_ID/WORK_TYPE/FILE_NAME/FILE_LENGTH/FILE_SIZE/RECORDING_STARTED_DATE/RECORDING_FINISHED_DATE/UPLOAD_DATE/TRANSCRIPTION_STARTED_DATE/TRANSCRIPTION_FINISHED_DATE - * @type {string} - * @memberof GetSortCriteriaResponse - */ - 'paramName': string; + /** + * ASC/DESC + * @type {string} + * @memberof GetSortCriteriaResponse + */ + direction: string; + /** + * JOB_NUMBER/STATUS/ENCRYPTION/AUTHOR_ID/WORK_TYPE/FILE_NAME/FILE_LENGTH/FILE_SIZE/RECORDING_STARTED_DATE/RECORDING_FINISHED_DATE/UPLOAD_DATE/TRANSCRIPTION_STARTED_DATE/TRANSCRIPTION_FINISHED_DATE + * @type {string} + * @memberof GetSortCriteriaResponse + */ + paramName: string; } /** - * + * * @export * @interface GetTypistGroupsResponse */ export interface GetTypistGroupsResponse { - /** - * - * @type {Array} - * @memberof GetTypistGroupsResponse - */ - 'typistGroups': Array; + /** + * + * @type {Array} + * @memberof GetTypistGroupsResponse + */ + typistGroups: Array; } /** - * + * * @export * @interface GetTypistsResponse */ export interface GetTypistsResponse { - /** - * - * @type {Array} - * @memberof GetTypistsResponse - */ - 'typists': Array; + /** + * + * @type {Array} + * @memberof GetTypistsResponse + */ + typists: Array; } /** - * + * * @export * @interface GetUsersResponse */ export interface GetUsersResponse { - /** - * - * @type {Array} - * @memberof GetUsersResponse - */ - 'users': Array; + /** + * + * @type {Array} + * @memberof GetUsersResponse + */ + users: Array; } /** - * + * * @export * @interface IssueCardLicensesRequest */ export interface IssueCardLicensesRequest { - /** - * - * @type {number} - * @memberof IssueCardLicensesRequest - */ - 'createCount': number; + /** + * + * @type {number} + * @memberof IssueCardLicensesRequest + */ + createCount: number; } /** - * + * * @export * @interface IssueCardLicensesResponse */ export interface IssueCardLicensesResponse { - /** - * - * @type {Array} - * @memberof IssueCardLicensesResponse - */ - 'cardLicenseKeys': Array; + /** + * + * @type {Array} + * @memberof IssueCardLicensesResponse + */ + cardLicenseKeys: Array; } /** - * + * * @export * @interface IssueLicenseRequest */ export interface IssueLicenseRequest { - /** - * 注文元アカウントID - * @type {number} - * @memberof IssueLicenseRequest - */ - 'orderedAccountId': number; - /** - * POナンバー - * @type {string} - * @memberof IssueLicenseRequest - */ - 'poNumber': string; + /** + * 注文元アカウントID + * @type {number} + * @memberof IssueLicenseRequest + */ + orderedAccountId: number; + /** + * POナンバー + * @type {string} + * @memberof IssueLicenseRequest + */ + poNumber: string; } /** - * + * * @export * @interface LicenseOrder */ export interface LicenseOrder { - /** - * 注文日付 - * @type {string} - * @memberof LicenseOrder - */ - 'orderDate': string; - /** - * 発行日付 - * @type {string} - * @memberof LicenseOrder - */ - 'issueDate': string; - /** - * 注文数 - * @type {number} - * @memberof LicenseOrder - */ - 'numberOfOrder': number; - /** - * POナンバー - * @type {string} - * @memberof LicenseOrder - */ - 'poNumber': string; - /** - * 注文状態 - * @type {string} - * @memberof LicenseOrder - */ - 'status': string; + /** + * 注文日付 + * @type {string} + * @memberof LicenseOrder + */ + orderDate: string; + /** + * 発行日付 + * @type {string} + * @memberof LicenseOrder + */ + issueDate: string; + /** + * 注文数 + * @type {number} + * @memberof LicenseOrder + */ + numberOfOrder: number; + /** + * POナンバー + * @type {string} + * @memberof LicenseOrder + */ + poNumber: string; + /** + * 注文状態 + * @type {string} + * @memberof LicenseOrder + */ + status: string; } /** - * + * * @export * @interface OptionItem */ export interface OptionItem { - /** - * Option Itemのラベル - * @type {string} - * @memberof OptionItem - */ - 'label': string; - /** - * 項目タイプ 1:Blank/2:Default/3:前の値 - * @type {number} - * @memberof OptionItem - */ - 'initialValueType': number; - /** - * typeでDefaultを選択した場合のデフォルト値 - * @type {string} - * @memberof OptionItem - */ - 'defaultValue': string; + /** + * Option Itemのラベル + * @type {string} + * @memberof OptionItem + */ + label: string; + /** + * 項目タイプ 1:Blank/2:Default/3:前の値 + * @type {number} + * @memberof OptionItem + */ + initialValueType: number; + /** + * typeでDefaultを選択した場合のデフォルト値 + * @type {string} + * @memberof OptionItem + */ + defaultValue: string; } /** - * + * * @export * @interface OptionItemList */ export interface OptionItemList { - /** - * - * @type {string} - * @memberof OptionItemList - */ - 'workTypeId': string; - /** - * 1WorkTypeIDにつき、10個まで登録可能 - * @type {Array} - * @memberof OptionItemList - */ - 'optionItemList': Array; + /** + * + * @type {string} + * @memberof OptionItemList + */ + workTypeId: string; + /** + * 1WorkTypeIDにつき、10個まで登録可能 + * @type {Array} + * @memberof OptionItemList + */ + optionItemList: Array; } /** - * + * * @export * @interface PartnerLicenseInfo */ export interface PartnerLicenseInfo { - /** - * アカウントID - * @type {number} - * @memberof PartnerLicenseInfo - */ - 'accountId': number; - /** - * 階層 - * @type {number} - * @memberof PartnerLicenseInfo - */ - 'tier': number; - /** - * アカウント名 - * @type {string} - * @memberof PartnerLicenseInfo - */ - 'companyName': string; - /** - * 保有している有効期限が未設定あるいは有効期限内のライセンス数 - * @type {number} - * @memberof PartnerLicenseInfo - */ - 'stockLicense': number; - /** - * 子アカウントからの、未発行状態あるいは発行キャンセルされた注文の総ライセンス数 - * @type {number} - * @memberof PartnerLicenseInfo - */ - 'issuedRequested': number; - /** - * 不足数({Stock license} - {Issue Requested}) - * @type {number} - * @memberof PartnerLicenseInfo - */ - 'shortage': number; - /** - * 未発行状態あるいは発行キャンセルされた注文の総ライセンス数(=IssueRequestingのStatusの注文の総ライセンス数) - * @type {number} - * @memberof PartnerLicenseInfo - */ - 'issueRequesting': number; + /** + * アカウントID + * @type {number} + * @memberof PartnerLicenseInfo + */ + accountId: number; + /** + * 階層 + * @type {number} + * @memberof PartnerLicenseInfo + */ + tier: number; + /** + * アカウント名 + * @type {string} + * @memberof PartnerLicenseInfo + */ + companyName: string; + /** + * 保有している有効期限が未設定あるいは有効期限内のライセンス数 + * @type {number} + * @memberof PartnerLicenseInfo + */ + stockLicense: number; + /** + * 子アカウントからの、未発行状態あるいは発行キャンセルされた注文の総ライセンス数 + * @type {number} + * @memberof PartnerLicenseInfo + */ + issuedRequested: number; + /** + * 不足数({Stock license} - {Issue Requested}) + * @type {number} + * @memberof PartnerLicenseInfo + */ + shortage: number; + /** + * 未発行状態あるいは発行キャンセルされた注文の総ライセンス数(=IssueRequestingのStatusの注文の総ライセンス数) + * @type {number} + * @memberof PartnerLicenseInfo + */ + issueRequesting: number; } /** - * + * * @export * @interface PostCheckoutPermissionRequest */ export interface PostCheckoutPermissionRequest { - /** - * 文字起こしに着手可能(チェックアウト可能)にしたい、グループ個人の一覧 - * @type {Array} - * @memberof PostCheckoutPermissionRequest - */ - 'assignees': Array; + /** + * 文字起こしに着手可能(チェックアウト可能)にしたい、グループ個人の一覧 + * @type {Array} + * @memberof PostCheckoutPermissionRequest + */ + assignees: Array; } /** - * + * * @export * @interface PostSortCriteriaRequest */ export interface PostSortCriteriaRequest { - /** - * ASC/DESC - * @type {string} - * @memberof PostSortCriteriaRequest - */ - 'direction': string; - /** - * JOB_NUMBER/STATUS/ENCRYPTION/AUTHOR_ID/WORK_TYPE/FILE_NAME/FILE_LENGTH/FILE_SIZE/RECORDING_STARTED_DATE/RECORDING_FINISHED_DATE/UPLOAD_DATE/TRANSCRIPTION_STARTED_DATE/TRANSCRIPTION_FINISHED_DATE - * @type {string} - * @memberof PostSortCriteriaRequest - */ - 'paramName': string; + /** + * ASC/DESC + * @type {string} + * @memberof PostSortCriteriaRequest + */ + direction: string; + /** + * JOB_NUMBER/STATUS/ENCRYPTION/AUTHOR_ID/WORK_TYPE/FILE_NAME/FILE_LENGTH/FILE_SIZE/RECORDING_STARTED_DATE/RECORDING_FINISHED_DATE/UPLOAD_DATE/TRANSCRIPTION_STARTED_DATE/TRANSCRIPTION_FINISHED_DATE + * @type {string} + * @memberof PostSortCriteriaRequest + */ + paramName: string; } /** - * + * * @export * @interface PostUpdateUserRequest */ export interface PostUpdateUserRequest { - /** - * - * @type {number} - * @memberof PostUpdateUserRequest - */ - 'id': number; - /** - * none/author/typist - * @type {string} - * @memberof PostUpdateUserRequest - */ - 'role': string; - /** - * - * @type {string} - * @memberof PostUpdateUserRequest - */ - 'authorId'?: string; - /** - * - * @type {boolean} - * @memberof PostUpdateUserRequest - */ - 'autoRenew': boolean; - /** - * - * @type {boolean} - * @memberof PostUpdateUserRequest - */ - 'licenseAlart': boolean; - /** - * - * @type {boolean} - * @memberof PostUpdateUserRequest - */ - 'notification': boolean; - /** - * - * @type {boolean} - * @memberof PostUpdateUserRequest - */ - 'encryption'?: boolean; - /** - * - * @type {string} - * @memberof PostUpdateUserRequest - */ - 'encryptionPassword'?: string; - /** - * - * @type {boolean} - * @memberof PostUpdateUserRequest - */ - 'prompt'?: boolean; + /** + * + * @type {number} + * @memberof PostUpdateUserRequest + */ + id: number; + /** + * none/author/typist + * @type {string} + * @memberof PostUpdateUserRequest + */ + role: string; + /** + * + * @type {string} + * @memberof PostUpdateUserRequest + */ + authorId?: string; + /** + * + * @type {boolean} + * @memberof PostUpdateUserRequest + */ + autoRenew: boolean; + /** + * + * @type {boolean} + * @memberof PostUpdateUserRequest + */ + licenseAlart: boolean; + /** + * + * @type {boolean} + * @memberof PostUpdateUserRequest + */ + notification: boolean; + /** + * + * @type {boolean} + * @memberof PostUpdateUserRequest + */ + encryption?: boolean; + /** + * + * @type {string} + * @memberof PostUpdateUserRequest + */ + encryptionPassword?: string; + /** + * + * @type {boolean} + * @memberof PostUpdateUserRequest + */ + prompt?: boolean; } /** - * + * * @export * @interface RegisterRequest */ export interface RegisterRequest { - /** - * wns or apns - * @type {string} - * @memberof RegisterRequest - */ - 'pns': string; - /** - * wnsのチャネルURI or apnsのデバイストークン - * @type {string} - * @memberof RegisterRequest - */ - 'handler': string; + /** + * wns or apns + * @type {string} + * @memberof RegisterRequest + */ + pns: string; + /** + * wnsのチャネルURI or apnsのデバイストークン + * @type {string} + * @memberof RegisterRequest + */ + handler: string; } /** - * + * * @export * @interface SignupRequest */ export interface SignupRequest { - /** - * - * @type {string} - * @memberof SignupRequest - */ - 'name': string; - /** - * none/author/typist - * @type {string} - * @memberof SignupRequest - */ - 'role': string; - /** - * - * @type {string} - * @memberof SignupRequest - */ - 'authorId'?: string; - /** - * - * @type {string} - * @memberof SignupRequest - */ - 'email': string; - /** - * - * @type {boolean} - * @memberof SignupRequest - */ - 'autoRenew': boolean; - /** - * - * @type {boolean} - * @memberof SignupRequest - */ - 'licenseAlert': boolean; - /** - * - * @type {boolean} - * @memberof SignupRequest - */ - 'notification': boolean; - /** - * - * @type {boolean} - * @memberof SignupRequest - */ - 'encryption'?: boolean; - /** - * - * @type {string} - * @memberof SignupRequest - */ - 'encryptionPassword'?: string; - /** - * - * @type {boolean} - * @memberof SignupRequest - */ - 'prompt'?: boolean; + /** + * + * @type {string} + * @memberof SignupRequest + */ + name: string; + /** + * none/author/typist + * @type {string} + * @memberof SignupRequest + */ + role: string; + /** + * + * @type {string} + * @memberof SignupRequest + */ + authorId?: string; + /** + * + * @type {string} + * @memberof SignupRequest + */ + email: string; + /** + * + * @type {boolean} + * @memberof SignupRequest + */ + autoRenew: boolean; + /** + * + * @type {boolean} + * @memberof SignupRequest + */ + licenseAlert: boolean; + /** + * + * @type {boolean} + * @memberof SignupRequest + */ + notification: boolean; + /** + * + * @type {boolean} + * @memberof SignupRequest + */ + encryption?: boolean; + /** + * + * @type {string} + * @memberof SignupRequest + */ + encryptionPassword?: string; + /** + * + * @type {boolean} + * @memberof SignupRequest + */ + prompt?: boolean; } /** - * + * * @export * @interface Task */ export interface Task { - /** - * ODMS Cloud上の音声ファイルID - * @type {number} - * @memberof Task - */ - 'audioFileId': number; - /** - * AuthorID - * @type {string} - * @memberof Task - */ - 'authorId': string; - /** - * - * @type {string} - * @memberof Task - */ - 'workType': string; - /** - * 音声ファイルに紐づくOption Itemの一覧(10個固定) - * @type {Array} - * @memberof Task - */ - 'optionItemList': Array; - /** - * 音声ファイルのBlob Storage上での保存場所(ファイル名含む)のURL - * @type {string} - * @memberof Task - */ - 'url': string; - /** - * 音声ファイル名 - * @type {string} - * @memberof Task - */ - 'fileName': string; - /** - * 音声ファイルの録音時間(ミリ秒の整数値) - * @type {string} - * @memberof Task - */ - 'audioDuration': string; - /** - * 音声ファイルの録音開始日時(yyyy-mm-ddThh:mm:ss.sss) - * @type {string} - * @memberof Task - */ - 'audioCreatedDate': string; - /** - * 音声ファイルの録音終了日時(yyyy-mm-ddThh:mm:ss.sss) - * @type {string} - * @memberof Task - */ - 'audioFinishedDate': string; - /** - * 音声ファイルのアップロード日時(yyyy-mm-ddThh:mm:ss.sss) - * @type {string} - * @memberof Task - */ - 'audioUploadedDate': string; - /** - * 音声ファイルのファイルサイズ(Byte) - * @type {number} - * @memberof Task - */ - 'fileSize': number; - /** - * 音声ファイルの優先度 \"00\":Normal / \"01\":High - * @type {string} - * @memberof Task - */ - 'priority': string; - /** - * 録音形式: DSS/DS2(SP)/DS2(QP) - * @type {string} - * @memberof Task - */ - 'audioFormat': string; - /** - * コメント - * @type {string} - * @memberof Task - */ - 'comment': string; - /** - * - * @type {boolean} - * @memberof Task - */ - 'isEncrypted': boolean; - /** - * JOBナンバー - * @type {string} - * @memberof Task - */ - 'jobNumber': string; - /** - * - * @type {TaskTypist} - * @memberof Task - */ - 'typist'?: TaskTypist; - /** - * 文字起こしに着手できる(チェックアウト可能な)、タスクにアサインされているグループ/個人の一覧 - * @type {Array} - * @memberof Task - */ - 'assignees': Array; - /** - * 音声ファイルのファイルステータス Uploaded / Pending / InProgress / Finished / Backup - * @type {string} - * @memberof Task - */ - 'status': string; - /** - * 文字起こし開始日時(yyyy-mm-ddThh:mm:ss.sss) - * @type {string} - * @memberof Task - */ - 'transcriptionStartedDate'?: string; - /** - * 文字起こし終了日時(yyyy-mm-ddThh:mm:ss.sss) - * @type {string} - * @memberof Task - */ - 'transcriptionFinishedDate'?: string; + /** + * ODMS Cloud上の音声ファイルID + * @type {number} + * @memberof Task + */ + audioFileId: number; + /** + * AuthorID + * @type {string} + * @memberof Task + */ + authorId: string; + /** + * + * @type {string} + * @memberof Task + */ + workType: string; + /** + * 音声ファイルに紐づくOption Itemの一覧(10個固定) + * @type {Array} + * @memberof Task + */ + optionItemList: Array; + /** + * 音声ファイルのBlob Storage上での保存場所(ファイル名含む)のURL + * @type {string} + * @memberof Task + */ + url: string; + /** + * 音声ファイル名 + * @type {string} + * @memberof Task + */ + fileName: string; + /** + * 音声ファイルの録音時間(ミリ秒の整数値) + * @type {string} + * @memberof Task + */ + audioDuration: string; + /** + * 音声ファイルの録音開始日時(yyyy-mm-ddThh:mm:ss.sss) + * @type {string} + * @memberof Task + */ + audioCreatedDate: string; + /** + * 音声ファイルの録音終了日時(yyyy-mm-ddThh:mm:ss.sss) + * @type {string} + * @memberof Task + */ + audioFinishedDate: string; + /** + * 音声ファイルのアップロード日時(yyyy-mm-ddThh:mm:ss.sss) + * @type {string} + * @memberof Task + */ + audioUploadedDate: string; + /** + * 音声ファイルのファイルサイズ(Byte) + * @type {number} + * @memberof Task + */ + fileSize: number; + /** + * 音声ファイルの優先度 \"00\":Normal / \"01\":High + * @type {string} + * @memberof Task + */ + priority: string; + /** + * 録音形式: DSS/DS2(SP)/DS2(QP) + * @type {string} + * @memberof Task + */ + audioFormat: string; + /** + * コメント + * @type {string} + * @memberof Task + */ + comment: string; + /** + * + * @type {boolean} + * @memberof Task + */ + isEncrypted: boolean; + /** + * JOBナンバー + * @type {string} + * @memberof Task + */ + jobNumber: string; + /** + * + * @type {TaskTypist} + * @memberof Task + */ + typist?: TaskTypist; + /** + * 文字起こしに着手できる(チェックアウト可能な)、タスクにアサインされているグループ/個人の一覧 + * @type {Array} + * @memberof Task + */ + assignees: Array; + /** + * 音声ファイルのファイルステータス Uploaded / Pending / InProgress / Finished / Backup + * @type {string} + * @memberof Task + */ + status: string; + /** + * 文字起こし開始日時(yyyy-mm-ddThh:mm:ss.sss) + * @type {string} + * @memberof Task + */ + transcriptionStartedDate?: string; + /** + * 文字起こし終了日時(yyyy-mm-ddThh:mm:ss.sss) + * @type {string} + * @memberof Task + */ + transcriptionFinishedDate?: string; } /** * 割り当てられたユーザー @@ -1191,785 +1290,1169 @@ export interface Task { * @interface TaskTypist */ export interface TaskTypist { - /** - * TypistのユーザーID - * @type {number} - * @memberof TaskTypist - */ - 'id': number; - /** - * Typistのユーザー名 - * @type {string} - * @memberof TaskTypist - */ - 'name': string; + /** + * TypistのユーザーID + * @type {number} + * @memberof TaskTypist + */ + id: number; + /** + * Typistのユーザー名 + * @type {string} + * @memberof TaskTypist + */ + name: string; } /** - * + * * @export * @interface TasksResponse */ export interface TasksResponse { - /** - * タスクの取得件数(指定しない場合はデフォルト値) - * @type {number} - * @memberof TasksResponse - */ - 'limit': number; - /** - * オフセット(何件目から取得するか 設定しない場合はデフォルト値) - * @type {number} - * @memberof TasksResponse - */ - 'offset': number; - /** - * タスクの総件数 - * @type {number} - * @memberof TasksResponse - */ - 'total': number; - /** - * 音声ファイル/タスク一覧 - * @type {Array} - * @memberof TasksResponse - */ - 'tasks': Array; + /** + * タスクの取得件数(指定しない場合はデフォルト値) + * @type {number} + * @memberof TasksResponse + */ + limit: number; + /** + * オフセット(何件目から取得するか 設定しない場合はデフォルト値) + * @type {number} + * @memberof TasksResponse + */ + offset: number; + /** + * タスクの総件数 + * @type {number} + * @memberof TasksResponse + */ + total: number; + /** + * 音声ファイル/タスク一覧 + * @type {Array} + * @memberof TasksResponse + */ + tasks: Array; } /** - * + * * @export * @interface TemplateDownloadLocationResponse */ export interface TemplateDownloadLocationResponse { - /** - * - * @type {string} - * @memberof TemplateDownloadLocationResponse - */ - 'url': string; + /** + * + * @type {string} + * @memberof TemplateDownloadLocationResponse + */ + url: string; } /** - * + * * @export * @interface TokenRequest */ export interface TokenRequest { - /** - * - * @type {string} - * @memberof TokenRequest - */ - 'idToken': string; - /** - * web or mobile or desktop - * @type {string} - * @memberof TokenRequest - */ - 'type': string; + /** + * + * @type {string} + * @memberof TokenRequest + */ + idToken: string; + /** + * web or mobile or desktop + * @type {string} + * @memberof TokenRequest + */ + type: string; } /** - * + * * @export * @interface TokenResponse */ export interface TokenResponse { - /** - * - * @type {string} - * @memberof TokenResponse - */ - 'refreshToken': string; - /** - * - * @type {string} - * @memberof TokenResponse - */ - 'accessToken': string; + /** + * + * @type {string} + * @memberof TokenResponse + */ + refreshToken: string; + /** + * + * @type {string} + * @memberof TokenResponse + */ + accessToken: string; } /** - * + * * @export * @interface Typist */ export interface Typist { - /** - * TypistのユーザーID - * @type {number} - * @memberof Typist - */ - 'id': number; - /** - * Typistのユーザー名 - * @type {string} - * @memberof Typist - */ - 'name': string; + /** + * TypistのユーザーID + * @type {number} + * @memberof Typist + */ + id: number; + /** + * Typistのユーザー名 + * @type {string} + * @memberof Typist + */ + name: string; } /** - * + * * @export * @interface TypistGroup */ export interface TypistGroup { - /** - * TypistGroupのID - * @type {number} - * @memberof TypistGroup - */ - 'id': number; - /** - * TypistGroup名 - * @type {string} - * @memberof TypistGroup - */ - 'name': string; + /** + * TypistGroupのID + * @type {number} + * @memberof TypistGroup + */ + id: number; + /** + * TypistGroup名 + * @type {string} + * @memberof TypistGroup + */ + name: string; } /** - * + * * @export * @interface User */ export interface User { - /** - * - * @type {number} - * @memberof User - */ - 'id': number; - /** - * - * @type {string} - * @memberof User - */ - 'name': string; - /** - * none/author/typist - * @type {string} - * @memberof User - */ - 'role': string; - /** - * - * @type {string} - * @memberof User - */ - 'authorId'?: string; - /** - * - * @type {Array} - * @memberof User - */ - 'typistGroupName': Array; - /** - * - * @type {string} - * @memberof User - */ - 'email': string; - /** - * - * @type {boolean} - * @memberof User - */ - 'emailVerified': boolean; - /** - * - * @type {boolean} - * @memberof User - */ - 'autoRenew': boolean; - /** - * - * @type {boolean} - * @memberof User - */ - 'licenseAlert': boolean; - /** - * - * @type {boolean} - * @memberof User - */ - 'notification': boolean; - /** - * - * @type {boolean} - * @memberof User - */ - 'encryption': boolean; - /** - * - * @type {boolean} - * @memberof User - */ - 'prompt': boolean; - /** - * - * @type {string} - * @memberof User - */ - 'expiration'?: string; - /** - * - * @type {number} - * @memberof User - */ - 'remaining'?: number; - /** - * Normal/NoLicense/Alert/Renew - * @type {string} - * @memberof User - */ - 'licenseStatus': string; + /** + * + * @type {number} + * @memberof User + */ + id: number; + /** + * + * @type {string} + * @memberof User + */ + name: string; + /** + * none/author/typist + * @type {string} + * @memberof User + */ + role: string; + /** + * + * @type {string} + * @memberof User + */ + authorId?: string; + /** + * + * @type {Array} + * @memberof User + */ + typistGroupName: Array; + /** + * + * @type {string} + * @memberof User + */ + email: string; + /** + * + * @type {boolean} + * @memberof User + */ + emailVerified: boolean; + /** + * + * @type {boolean} + * @memberof User + */ + autoRenew: boolean; + /** + * + * @type {boolean} + * @memberof User + */ + licenseAlert: boolean; + /** + * + * @type {boolean} + * @memberof User + */ + notification: boolean; + /** + * + * @type {boolean} + * @memberof User + */ + encryption: boolean; + /** + * + * @type {boolean} + * @memberof User + */ + prompt: boolean; + /** + * + * @type {string} + * @memberof User + */ + expiration?: string; + /** + * + * @type {number} + * @memberof User + */ + remaining?: number; + /** + * Normal/NoLicense/Alert/Renew + * @type {string} + * @memberof User + */ + licenseStatus: string; } /** * AccountsApi - axios parameter creator * @export */ -export const AccountsApiAxiosParamCreator = function (configuration?: Configuration) { - return { - /** - * - * @summary - * @param {CreateAccountRequest} createAccountRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - createAccount: async (createAccountRequest: CreateAccountRequest, options: AxiosRequestConfig = {}): Promise => { - // verify required parameter 'createAccountRequest' is not null or undefined - assertParamExists('createAccount', 'createAccountRequest', createAccountRequest) - const localVarPath = `/accounts`; - // 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; - } +export const AccountsApiAxiosParamCreator = function ( + configuration?: Configuration +) { + return { + /** + * + * @summary + * @param {CreateAccountRequest} createAccountRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + createAccount: async ( + createAccountRequest: CreateAccountRequest, + options: AxiosRequestConfig = {} + ): Promise => { + // verify required parameter 'createAccountRequest' is not null or undefined + assertParamExists( + "createAccount", + "createAccountRequest", + createAccountRequest + ); + const localVarPath = `/accounts`; + // 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; + const localVarRequestOptions = { + method: "POST", + ...baseOptions, + ...options, + }; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + localVarHeaderParameter["Content-Type"] = "application/json"; - - localVarHeaderParameter['Content-Type'] = 'application/json'; + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = + baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = { + ...localVarHeaderParameter, + ...headersFromBaseOptions, + ...options.headers, + }; + localVarRequestOptions.data = serializeDataIfNeeded( + createAccountRequest, + localVarRequestOptions, + configuration + ); - setSearchParams(localVarUrlObj, localVarQueryParameter); - let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; - localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; - localVarRequestOptions.data = serializeDataIfNeeded(createAccountRequest, localVarRequestOptions, configuration) + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * + * @summary + * @param {CreatePartnerAccountRequest} createPartnerAccountRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + createPartnerAccount: async ( + createPartnerAccountRequest: CreatePartnerAccountRequest, + options: AxiosRequestConfig = {} + ): Promise => { + // verify required parameter 'createPartnerAccountRequest' is not null or undefined + assertParamExists( + "createPartnerAccount", + "createPartnerAccountRequest", + createPartnerAccountRequest + ); + const localVarPath = `/accounts/partner`; + // 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; + } - return { - url: toPathString(localVarUrlObj), - options: localVarRequestOptions, - }; - }, - /** - * - * @summary - * @param {CreatePartnerAccountRequest} createPartnerAccountRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - createPartnerAccount: async (createPartnerAccountRequest: CreatePartnerAccountRequest, options: AxiosRequestConfig = {}): Promise => { - // verify required parameter 'createPartnerAccountRequest' is not null or undefined - assertParamExists('createPartnerAccount', 'createPartnerAccountRequest', createPartnerAccountRequest) - const localVarPath = `/accounts/partner`; - // 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; - 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); - // 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( + createPartnerAccountRequest, + localVarRequestOptions, + configuration + ); - - localVarHeaderParameter['Content-Type'] = 'application/json'; + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * + * @summary + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getDealers: async ( + options: AxiosRequestConfig = {} + ): Promise => { + const localVarPath = `/accounts/dealers`; + // 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; + } - setSearchParams(localVarUrlObj, localVarQueryParameter); - let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; - localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; - localVarRequestOptions.data = serializeDataIfNeeded(createPartnerAccountRequest, localVarRequestOptions, configuration) + const localVarRequestOptions = { + method: "GET", + ...baseOptions, + ...options, + }; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; - return { - url: toPathString(localVarUrlObj), - options: localVarRequestOptions, - }; - }, - /** - * 指定したアカウントのライセンス集計情報を取得します - * @summary - * @param {GetLicenseSummaryRequest} getLicenseSummaryRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - getLicenseSummary: async (getLicenseSummaryRequest: GetLicenseSummaryRequest, options: AxiosRequestConfig = {}): Promise => { - // verify required parameter 'getLicenseSummaryRequest' is not null or undefined - assertParamExists('getLicenseSummary', 'getLicenseSummaryRequest', getLicenseSummaryRequest) - const localVarPath = `/accounts/licenses/summary`; - // 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; - } + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = + baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = { + ...localVarHeaderParameter, + ...headersFromBaseOptions, + ...options.headers, + }; - const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options}; - const localVarHeaderParameter = {} as any; - const localVarQueryParameter = {} as any; + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * 指定したアカウントのライセンス集計情報を取得します + * @summary + * @param {GetLicenseSummaryRequest} getLicenseSummaryRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getLicenseSummary: async ( + getLicenseSummaryRequest: GetLicenseSummaryRequest, + options: AxiosRequestConfig = {} + ): Promise => { + // verify required parameter 'getLicenseSummaryRequest' is not null or undefined + assertParamExists( + "getLicenseSummary", + "getLicenseSummaryRequest", + getLicenseSummaryRequest + ); + const localVarPath = `/accounts/licenses/summary`; + // 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; + } - // authentication bearer required - // http bearer authentication required - await setBearerAuthToObject(localVarHeaderParameter, configuration) + 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'; + localVarHeaderParameter["Content-Type"] = "application/json"; - setSearchParams(localVarUrlObj, localVarQueryParameter); - let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; - localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; - localVarRequestOptions.data = serializeDataIfNeeded(getLicenseSummaryRequest, localVarRequestOptions, configuration) + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = + baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = { + ...localVarHeaderParameter, + ...headersFromBaseOptions, + ...options.headers, + }; + localVarRequestOptions.data = serializeDataIfNeeded( + getLicenseSummaryRequest, + localVarRequestOptions, + configuration + ); - return { - url: toPathString(localVarUrlObj), - options: localVarRequestOptions, - }; - }, - /** - * ログインしているユーザーのアカウント情報を取得します - * @summary - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - getMyAccount: async (options: AxiosRequestConfig = {}): Promise => { - const localVarPath = `/accounts/me`; - // 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; - } + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * ログインしているユーザーのアカウント情報を取得します + * @summary + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getMyAccount: async ( + options: AxiosRequestConfig = {} + ): Promise => { + const localVarPath = `/accounts/me`; + // 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; + 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) + // 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, + }; - - setSearchParams(localVarUrlObj, localVarQueryParameter); - let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; - localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * + * @summary + * @param {GetOrderHistoriesRequest} getOrderHistoriesRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getOrderHistories: async ( + getOrderHistoriesRequest: GetOrderHistoriesRequest, + options: AxiosRequestConfig = {} + ): Promise => { + // verify required parameter 'getOrderHistoriesRequest' is not null or undefined + assertParamExists( + "getOrderHistories", + "getOrderHistoriesRequest", + getOrderHistoriesRequest + ); + const localVarPath = `/accounts/order-histories`; + // 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; + } - return { - url: toPathString(localVarUrlObj), - options: localVarRequestOptions, - }; - }, - /** - * - * @summary - * @param {GetOrderHistoriesRequest} getOrderHistoriesRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - getOrderHistories: async (getOrderHistoriesRequest: GetOrderHistoriesRequest, options: AxiosRequestConfig = {}): Promise => { - // verify required parameter 'getOrderHistoriesRequest' is not null or undefined - assertParamExists('getOrderHistories', 'getOrderHistoriesRequest', getOrderHistoriesRequest) - const localVarPath = `/accounts/order-histories`; - // 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; - 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); - // 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( + getOrderHistoriesRequest, + localVarRequestOptions, + configuration + ); - - localVarHeaderParameter['Content-Type'] = 'application/json'; + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * + * @summary + * @param {GetPartnerLicensesRequest} getPartnerLicensesRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getPartnerLicenses: async ( + getPartnerLicensesRequest: GetPartnerLicensesRequest, + options: AxiosRequestConfig = {} + ): Promise => { + // verify required parameter 'getPartnerLicensesRequest' is not null or undefined + assertParamExists( + "getPartnerLicenses", + "getPartnerLicensesRequest", + getPartnerLicensesRequest + ); + const localVarPath = `/accounts/partner-licenses`; + // 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; + } - setSearchParams(localVarUrlObj, localVarQueryParameter); - let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; - localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; - localVarRequestOptions.data = serializeDataIfNeeded(getOrderHistoriesRequest, localVarRequestOptions, configuration) + const localVarRequestOptions = { + method: "POST", + ...baseOptions, + ...options, + }; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; - return { - url: toPathString(localVarUrlObj), - options: localVarRequestOptions, - }; - }, - /** - * - * @summary - * @param {GetPartnerLicensesRequest} getPartnerLicensesRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - getPartnerLicenses: async (getPartnerLicensesRequest: GetPartnerLicensesRequest, options: AxiosRequestConfig = {}): Promise => { - // verify required parameter 'getPartnerLicensesRequest' is not null or undefined - assertParamExists('getPartnerLicenses', 'getPartnerLicensesRequest', getPartnerLicensesRequest) - const localVarPath = `/accounts/partner-licenses`; - // 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; - } + // authentication bearer required + // http bearer authentication required + await setBearerAuthToObject(localVarHeaderParameter, configuration); - const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options}; - const localVarHeaderParameter = {} as any; - const localVarQueryParameter = {} as any; + localVarHeaderParameter["Content-Type"] = "application/json"; - // 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, + }; + localVarRequestOptions.data = serializeDataIfNeeded( + getPartnerLicensesRequest, + localVarRequestOptions, + configuration + ); + 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; + } - - localVarHeaderParameter['Content-Type'] = 'application/json'; + const localVarRequestOptions = { + method: "GET", + ...baseOptions, + ...options, + }; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; - setSearchParams(localVarUrlObj, localVarQueryParameter); - let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; - localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; - localVarRequestOptions.data = serializeDataIfNeeded(getPartnerLicensesRequest, localVarRequestOptions, configuration) + // authentication bearer required + // http bearer authentication required + await setBearerAuthToObject(localVarHeaderParameter, configuration); - 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; - } + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = + baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = { + ...localVarHeaderParameter, + ...headersFromBaseOptions, + ...options.headers, + }; - const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; - const localVarHeaderParameter = {} as any; - const localVarQueryParameter = {} as any; + 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; + } - // authentication bearer required - // http bearer authentication required - await setBearerAuthToObject(localVarHeaderParameter, configuration) + 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}; + 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; - } + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * + * @summary + * @param {IssueLicenseRequest} issueLicenseRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + issueLicense: async ( + issueLicenseRequest: IssueLicenseRequest, + options: AxiosRequestConfig = {} + ): Promise => { + // verify required parameter 'issueLicenseRequest' is not null or undefined + assertParamExists( + "issueLicense", + "issueLicenseRequest", + issueLicenseRequest + ); + const localVarPath = `/accounts/licenses/issue`; + // 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; + 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) + // 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}; + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = + baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = { + ...localVarHeaderParameter, + ...headersFromBaseOptions, + ...options.headers, + }; + localVarRequestOptions.data = serializeDataIfNeeded( + issueLicenseRequest, + localVarRequestOptions, + configuration + ); - return { - url: toPathString(localVarUrlObj), - options: localVarRequestOptions, - }; - }, - /** - * - * @summary - * @param {IssueLicenseRequest} issueLicenseRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - issueLicense: async (issueLicenseRequest: IssueLicenseRequest, options: AxiosRequestConfig = {}): Promise => { - // verify required parameter 'issueLicenseRequest' is not null or undefined - assertParamExists('issueLicense', 'issueLicenseRequest', issueLicenseRequest) - const localVarPath = `/accounts/licenses/issue`; - // 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(issueLicenseRequest, localVarRequestOptions, configuration) - - return { - url: toPathString(localVarUrlObj), - options: localVarRequestOptions, - }; - }, - } + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + }; }; /** * AccountsApi - functional programming interface * @export */ -export const AccountsApiFp = function(configuration?: Configuration) { - const localVarAxiosParamCreator = AccountsApiAxiosParamCreator(configuration) - return { - /** - * - * @summary - * @param {CreateAccountRequest} createAccountRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - async createAccount(createAccountRequest: CreateAccountRequest, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.createAccount(createAccountRequest, options); - return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); - }, - /** - * - * @summary - * @param {CreatePartnerAccountRequest} createPartnerAccountRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - async createPartnerAccount(createPartnerAccountRequest: CreatePartnerAccountRequest, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.createPartnerAccount(createPartnerAccountRequest, options); - return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); - }, - /** - * 指定したアカウントのライセンス集計情報を取得します - * @summary - * @param {GetLicenseSummaryRequest} getLicenseSummaryRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - async getLicenseSummary(getLicenseSummaryRequest: GetLicenseSummaryRequest, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.getLicenseSummary(getLicenseSummaryRequest, options); - return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); - }, - /** - * ログインしているユーザーのアカウント情報を取得します - * @summary - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - async getMyAccount(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.getMyAccount(options); - return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); - }, - /** - * - * @summary - * @param {GetOrderHistoriesRequest} getOrderHistoriesRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - async getOrderHistories(getOrderHistoriesRequest: GetOrderHistoriesRequest, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.getOrderHistories(getOrderHistoriesRequest, options); - return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); - }, - /** - * - * @summary - * @param {GetPartnerLicensesRequest} getPartnerLicensesRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - async getPartnerLicenses(getPartnerLicensesRequest: GetPartnerLicensesRequest, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.getPartnerLicenses(getPartnerLicensesRequest, 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); - }, - /** - * - * @summary - * @param {IssueLicenseRequest} issueLicenseRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - async issueLicense(issueLicenseRequest: IssueLicenseRequest, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.issueLicense(issueLicenseRequest, options); - return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); - }, - } +export const AccountsApiFp = function (configuration?: Configuration) { + const localVarAxiosParamCreator = AccountsApiAxiosParamCreator(configuration); + return { + /** + * + * @summary + * @param {CreateAccountRequest} createAccountRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async createAccount( + createAccountRequest: CreateAccountRequest, + options?: AxiosRequestConfig + ): Promise< + (axios?: AxiosInstance, basePath?: string) => AxiosPromise + > { + const localVarAxiosArgs = await localVarAxiosParamCreator.createAccount( + createAccountRequest, + options + ); + return createRequestFunction( + localVarAxiosArgs, + globalAxios, + BASE_PATH, + configuration + ); + }, + /** + * + * @summary + * @param {CreatePartnerAccountRequest} createPartnerAccountRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async createPartnerAccount( + createPartnerAccountRequest: CreatePartnerAccountRequest, + options?: AxiosRequestConfig + ): Promise< + (axios?: AxiosInstance, basePath?: string) => AxiosPromise + > { + const localVarAxiosArgs = + await localVarAxiosParamCreator.createPartnerAccount( + createPartnerAccountRequest, + options + ); + return createRequestFunction( + localVarAxiosArgs, + globalAxios, + BASE_PATH, + configuration + ); + }, + /** + * + * @summary + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async getDealers( + options?: AxiosRequestConfig + ): Promise< + ( + axios?: AxiosInstance, + basePath?: string + ) => AxiosPromise + > { + const localVarAxiosArgs = await localVarAxiosParamCreator.getDealers( + options + ); + return createRequestFunction( + localVarAxiosArgs, + globalAxios, + BASE_PATH, + configuration + ); + }, + /** + * 指定したアカウントのライセンス集計情報を取得します + * @summary + * @param {GetLicenseSummaryRequest} getLicenseSummaryRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async getLicenseSummary( + getLicenseSummaryRequest: GetLicenseSummaryRequest, + options?: AxiosRequestConfig + ): Promise< + ( + axios?: AxiosInstance, + basePath?: string + ) => AxiosPromise + > { + const localVarAxiosArgs = + await localVarAxiosParamCreator.getLicenseSummary( + getLicenseSummaryRequest, + options + ); + return createRequestFunction( + localVarAxiosArgs, + globalAxios, + BASE_PATH, + configuration + ); + }, + /** + * ログインしているユーザーのアカウント情報を取得します + * @summary + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async getMyAccount( + options?: AxiosRequestConfig + ): Promise< + ( + axios?: AxiosInstance, + basePath?: string + ) => AxiosPromise + > { + const localVarAxiosArgs = await localVarAxiosParamCreator.getMyAccount( + options + ); + return createRequestFunction( + localVarAxiosArgs, + globalAxios, + BASE_PATH, + configuration + ); + }, + /** + * + * @summary + * @param {GetOrderHistoriesRequest} getOrderHistoriesRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async getOrderHistories( + getOrderHistoriesRequest: GetOrderHistoriesRequest, + options?: AxiosRequestConfig + ): Promise< + ( + axios?: AxiosInstance, + basePath?: string + ) => AxiosPromise + > { + const localVarAxiosArgs = + await localVarAxiosParamCreator.getOrderHistories( + getOrderHistoriesRequest, + options + ); + return createRequestFunction( + localVarAxiosArgs, + globalAxios, + BASE_PATH, + configuration + ); + }, + /** + * + * @summary + * @param {GetPartnerLicensesRequest} getPartnerLicensesRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async getPartnerLicenses( + getPartnerLicensesRequest: GetPartnerLicensesRequest, + options?: AxiosRequestConfig + ): Promise< + ( + axios?: AxiosInstance, + basePath?: string + ) => AxiosPromise + > { + const localVarAxiosArgs = + await localVarAxiosParamCreator.getPartnerLicenses( + getPartnerLicensesRequest, + 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 + ); + }, + /** + * + * @summary + * @param {IssueLicenseRequest} issueLicenseRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async issueLicense( + issueLicenseRequest: IssueLicenseRequest, + options?: AxiosRequestConfig + ): Promise< + (axios?: AxiosInstance, basePath?: string) => AxiosPromise + > { + const localVarAxiosArgs = await localVarAxiosParamCreator.issueLicense( + issueLicenseRequest, + options + ); + return createRequestFunction( + localVarAxiosArgs, + globalAxios, + BASE_PATH, + configuration + ); + }, + }; }; /** * AccountsApi - factory interface * @export */ -export const AccountsApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) { - const localVarFp = AccountsApiFp(configuration) - return { - /** - * - * @summary - * @param {CreateAccountRequest} createAccountRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - createAccount(createAccountRequest: CreateAccountRequest, options?: any): AxiosPromise { - return localVarFp.createAccount(createAccountRequest, options).then((request) => request(axios, basePath)); - }, - /** - * - * @summary - * @param {CreatePartnerAccountRequest} createPartnerAccountRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - createPartnerAccount(createPartnerAccountRequest: CreatePartnerAccountRequest, options?: any): AxiosPromise { - return localVarFp.createPartnerAccount(createPartnerAccountRequest, options).then((request) => request(axios, basePath)); - }, - /** - * 指定したアカウントのライセンス集計情報を取得します - * @summary - * @param {GetLicenseSummaryRequest} getLicenseSummaryRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - getLicenseSummary(getLicenseSummaryRequest: GetLicenseSummaryRequest, options?: any): AxiosPromise { - return localVarFp.getLicenseSummary(getLicenseSummaryRequest, options).then((request) => request(axios, basePath)); - }, - /** - * ログインしているユーザーのアカウント情報を取得します - * @summary - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - getMyAccount(options?: any): AxiosPromise { - return localVarFp.getMyAccount(options).then((request) => request(axios, basePath)); - }, - /** - * - * @summary - * @param {GetOrderHistoriesRequest} getOrderHistoriesRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - getOrderHistories(getOrderHistoriesRequest: GetOrderHistoriesRequest, options?: any): AxiosPromise { - return localVarFp.getOrderHistories(getOrderHistoriesRequest, options).then((request) => request(axios, basePath)); - }, - /** - * - * @summary - * @param {GetPartnerLicensesRequest} getPartnerLicensesRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - getPartnerLicenses(getPartnerLicensesRequest: GetPartnerLicensesRequest, options?: any): AxiosPromise { - return localVarFp.getPartnerLicenses(getPartnerLicensesRequest, 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)); - }, - /** - * - * @summary - * @param {IssueLicenseRequest} issueLicenseRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - issueLicense(issueLicenseRequest: IssueLicenseRequest, options?: any): AxiosPromise { - return localVarFp.issueLicense(issueLicenseRequest, options).then((request) => request(axios, basePath)); - }, - }; +export const AccountsApiFactory = function ( + configuration?: Configuration, + basePath?: string, + axios?: AxiosInstance +) { + const localVarFp = AccountsApiFp(configuration); + return { + /** + * + * @summary + * @param {CreateAccountRequest} createAccountRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + createAccount( + createAccountRequest: CreateAccountRequest, + options?: any + ): AxiosPromise { + return localVarFp + .createAccount(createAccountRequest, options) + .then((request) => request(axios, basePath)); + }, + /** + * + * @summary + * @param {CreatePartnerAccountRequest} createPartnerAccountRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + createPartnerAccount( + createPartnerAccountRequest: CreatePartnerAccountRequest, + options?: any + ): AxiosPromise { + return localVarFp + .createPartnerAccount(createPartnerAccountRequest, options) + .then((request) => request(axios, basePath)); + }, + /** + * + * @summary + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getDealers(options?: any): AxiosPromise { + return localVarFp + .getDealers(options) + .then((request) => request(axios, basePath)); + }, + /** + * 指定したアカウントのライセンス集計情報を取得します + * @summary + * @param {GetLicenseSummaryRequest} getLicenseSummaryRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getLicenseSummary( + getLicenseSummaryRequest: GetLicenseSummaryRequest, + options?: any + ): AxiosPromise { + return localVarFp + .getLicenseSummary(getLicenseSummaryRequest, options) + .then((request) => request(axios, basePath)); + }, + /** + * ログインしているユーザーのアカウント情報を取得します + * @summary + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getMyAccount(options?: any): AxiosPromise { + return localVarFp + .getMyAccount(options) + .then((request) => request(axios, basePath)); + }, + /** + * + * @summary + * @param {GetOrderHistoriesRequest} getOrderHistoriesRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getOrderHistories( + getOrderHistoriesRequest: GetOrderHistoriesRequest, + options?: any + ): AxiosPromise { + return localVarFp + .getOrderHistories(getOrderHistoriesRequest, options) + .then((request) => request(axios, basePath)); + }, + /** + * + * @summary + * @param {GetPartnerLicensesRequest} getPartnerLicensesRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getPartnerLicenses( + getPartnerLicensesRequest: GetPartnerLicensesRequest, + options?: any + ): AxiosPromise { + return localVarFp + .getPartnerLicenses(getPartnerLicensesRequest, 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)); + }, + /** + * + * @summary + * @param {IssueLicenseRequest} issueLicenseRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + issueLicense( + issueLicenseRequest: IssueLicenseRequest, + options?: any + ): AxiosPromise { + return localVarFp + .issueLicense(issueLicenseRequest, options) + .then((request) => request(axios, basePath)); + }, + }; }; /** @@ -1979,250 +2462,361 @@ export const AccountsApiFactory = function (configuration?: Configuration, baseP * @extends {BaseAPI} */ export class AccountsApi extends BaseAPI { - /** - * - * @summary - * @param {CreateAccountRequest} createAccountRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof AccountsApi - */ - public createAccount(createAccountRequest: CreateAccountRequest, options?: AxiosRequestConfig) { - return AccountsApiFp(this.configuration).createAccount(createAccountRequest, options).then((request) => request(this.axios, this.basePath)); - } + /** + * + * @summary + * @param {CreateAccountRequest} createAccountRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof AccountsApi + */ + public createAccount( + createAccountRequest: CreateAccountRequest, + options?: AxiosRequestConfig + ) { + return AccountsApiFp(this.configuration) + .createAccount(createAccountRequest, options) + .then((request) => request(this.axios, this.basePath)); + } - /** - * - * @summary - * @param {CreatePartnerAccountRequest} createPartnerAccountRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof AccountsApi - */ - public createPartnerAccount(createPartnerAccountRequest: CreatePartnerAccountRequest, options?: AxiosRequestConfig) { - return AccountsApiFp(this.configuration).createPartnerAccount(createPartnerAccountRequest, options).then((request) => request(this.axios, this.basePath)); - } + /** + * + * @summary + * @param {CreatePartnerAccountRequest} createPartnerAccountRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof AccountsApi + */ + public createPartnerAccount( + createPartnerAccountRequest: CreatePartnerAccountRequest, + options?: AxiosRequestConfig + ) { + return AccountsApiFp(this.configuration) + .createPartnerAccount(createPartnerAccountRequest, options) + .then((request) => request(this.axios, this.basePath)); + } - /** - * 指定したアカウントのライセンス集計情報を取得します - * @summary - * @param {GetLicenseSummaryRequest} getLicenseSummaryRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof AccountsApi - */ - public getLicenseSummary(getLicenseSummaryRequest: GetLicenseSummaryRequest, options?: AxiosRequestConfig) { - return AccountsApiFp(this.configuration).getLicenseSummary(getLicenseSummaryRequest, options).then((request) => request(this.axios, this.basePath)); - } + /** + * + * @summary + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof AccountsApi + */ + public getDealers(options?: AxiosRequestConfig) { + return AccountsApiFp(this.configuration) + .getDealers(options) + .then((request) => request(this.axios, this.basePath)); + } - /** - * ログインしているユーザーのアカウント情報を取得します - * @summary - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof AccountsApi - */ - public getMyAccount(options?: AxiosRequestConfig) { - return AccountsApiFp(this.configuration).getMyAccount(options).then((request) => request(this.axios, this.basePath)); - } + /** + * 指定したアカウントのライセンス集計情報を取得します + * @summary + * @param {GetLicenseSummaryRequest} getLicenseSummaryRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof AccountsApi + */ + public getLicenseSummary( + getLicenseSummaryRequest: GetLicenseSummaryRequest, + options?: AxiosRequestConfig + ) { + return AccountsApiFp(this.configuration) + .getLicenseSummary(getLicenseSummaryRequest, options) + .then((request) => request(this.axios, this.basePath)); + } - /** - * - * @summary - * @param {GetOrderHistoriesRequest} getOrderHistoriesRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof AccountsApi - */ - public getOrderHistories(getOrderHistoriesRequest: GetOrderHistoriesRequest, options?: AxiosRequestConfig) { - return AccountsApiFp(this.configuration).getOrderHistories(getOrderHistoriesRequest, options).then((request) => request(this.axios, this.basePath)); - } + /** + * ログインしているユーザーのアカウント情報を取得します + * @summary + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof AccountsApi + */ + public getMyAccount(options?: AxiosRequestConfig) { + return AccountsApiFp(this.configuration) + .getMyAccount(options) + .then((request) => request(this.axios, this.basePath)); + } - /** - * - * @summary - * @param {GetPartnerLicensesRequest} getPartnerLicensesRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof AccountsApi - */ - public getPartnerLicenses(getPartnerLicensesRequest: GetPartnerLicensesRequest, options?: AxiosRequestConfig) { - return AccountsApiFp(this.configuration).getPartnerLicenses(getPartnerLicensesRequest, options).then((request) => request(this.axios, this.basePath)); - } + /** + * + * @summary + * @param {GetOrderHistoriesRequest} getOrderHistoriesRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof AccountsApi + */ + public getOrderHistories( + getOrderHistoriesRequest: GetOrderHistoriesRequest, + options?: AxiosRequestConfig + ) { + return AccountsApiFp(this.configuration) + .getOrderHistories(getOrderHistoriesRequest, 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 {GetPartnerLicensesRequest} getPartnerLicensesRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof AccountsApi + */ + public getPartnerLicenses( + getPartnerLicensesRequest: GetPartnerLicensesRequest, + options?: AxiosRequestConfig + ) { + return AccountsApiFp(this.configuration) + .getPartnerLicenses(getPartnerLicensesRequest, 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)); - } + /** + * ログインしているユーザーのアカウント配下のタイピストグループ一覧を取得します + * @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 {IssueLicenseRequest} issueLicenseRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof AccountsApi - */ - public issueLicense(issueLicenseRequest: IssueLicenseRequest, options?: AxiosRequestConfig) { - return AccountsApiFp(this.configuration).issueLicense(issueLicenseRequest, 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)); + } + + /** + * + * @summary + * @param {IssueLicenseRequest} issueLicenseRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof AccountsApi + */ + public issueLicense( + issueLicenseRequest: IssueLicenseRequest, + options?: AxiosRequestConfig + ) { + return AccountsApiFp(this.configuration) + .issueLicense(issueLicenseRequest, options) + .then((request) => request(this.axios, this.basePath)); + } } - /** * AuthApi - axios parameter creator * @export */ -export const AuthApiAxiosParamCreator = function (configuration?: Configuration) { - return { - /** - * リフレッシュトークンを元にアクセストークンを再生成します - * @summary - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - accessToken: async (options: AxiosRequestConfig = {}): Promise => { - const localVarPath = `/auth/accessToken`; - // 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; - } +export const AuthApiAxiosParamCreator = function ( + configuration?: Configuration +) { + return { + /** + * リフレッシュトークンを元にアクセストークンを再生成します + * @summary + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + accessToken: async ( + options: AxiosRequestConfig = {} + ): Promise => { + const localVarPath = `/auth/accessToken`; + // 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; + 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) + // 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, + }; - - setSearchParams(localVarUrlObj, localVarQueryParameter); - let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; - localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * AzureADB2Cでのサインイン後に払いだされるIDトークンを元に認証用のアクセストークンとリフレッシュトークンを生成します + * @summary + * @param {TokenRequest} tokenRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + token: async ( + tokenRequest: TokenRequest, + options: AxiosRequestConfig = {} + ): Promise => { + // verify required parameter 'tokenRequest' is not null or undefined + assertParamExists("token", "tokenRequest", tokenRequest); + const localVarPath = `/auth/token`; + // 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; + } - return { - url: toPathString(localVarUrlObj), - options: localVarRequestOptions, - }; - }, - /** - * AzureADB2Cでのサインイン後に払いだされるIDトークンを元に認証用のアクセストークンとリフレッシュトークンを生成します - * @summary - * @param {TokenRequest} tokenRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - token: async (tokenRequest: TokenRequest, options: AxiosRequestConfig = {}): Promise => { - // verify required parameter 'tokenRequest' is not null or undefined - assertParamExists('token', 'tokenRequest', tokenRequest) - const localVarPath = `/auth/token`; - // 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; - const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options}; - const localVarHeaderParameter = {} as any; - const localVarQueryParameter = {} as any; + localVarHeaderParameter["Content-Type"] = "application/json"; + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = + baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = { + ...localVarHeaderParameter, + ...headersFromBaseOptions, + ...options.headers, + }; + localVarRequestOptions.data = serializeDataIfNeeded( + tokenRequest, + localVarRequestOptions, + 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(tokenRequest, localVarRequestOptions, configuration) - - return { - url: toPathString(localVarUrlObj), - options: localVarRequestOptions, - }; - }, - } + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + }; }; /** * AuthApi - functional programming interface * @export */ -export const AuthApiFp = function(configuration?: Configuration) { - const localVarAxiosParamCreator = AuthApiAxiosParamCreator(configuration) - return { - /** - * リフレッシュトークンを元にアクセストークンを再生成します - * @summary - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - async accessToken(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.accessToken(options); - return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); - }, - /** - * AzureADB2Cでのサインイン後に払いだされるIDトークンを元に認証用のアクセストークンとリフレッシュトークンを生成します - * @summary - * @param {TokenRequest} tokenRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - async token(tokenRequest: TokenRequest, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.token(tokenRequest, options); - return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); - }, - } +export const AuthApiFp = function (configuration?: Configuration) { + const localVarAxiosParamCreator = AuthApiAxiosParamCreator(configuration); + return { + /** + * リフレッシュトークンを元にアクセストークンを再生成します + * @summary + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async accessToken( + options?: AxiosRequestConfig + ): Promise< + ( + axios?: AxiosInstance, + basePath?: string + ) => AxiosPromise + > { + const localVarAxiosArgs = await localVarAxiosParamCreator.accessToken( + options + ); + return createRequestFunction( + localVarAxiosArgs, + globalAxios, + BASE_PATH, + configuration + ); + }, + /** + * AzureADB2Cでのサインイン後に払いだされるIDトークンを元に認証用のアクセストークンとリフレッシュトークンを生成します + * @summary + * @param {TokenRequest} tokenRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async token( + tokenRequest: TokenRequest, + options?: AxiosRequestConfig + ): Promise< + (axios?: AxiosInstance, basePath?: string) => AxiosPromise + > { + const localVarAxiosArgs = await localVarAxiosParamCreator.token( + tokenRequest, + options + ); + return createRequestFunction( + localVarAxiosArgs, + globalAxios, + BASE_PATH, + configuration + ); + }, + }; }; /** * AuthApi - factory interface * @export */ -export const AuthApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) { - const localVarFp = AuthApiFp(configuration) - return { - /** - * リフレッシュトークンを元にアクセストークンを再生成します - * @summary - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - accessToken(options?: any): AxiosPromise { - return localVarFp.accessToken(options).then((request) => request(axios, basePath)); - }, - /** - * AzureADB2Cでのサインイン後に払いだされるIDトークンを元に認証用のアクセストークンとリフレッシュトークンを生成します - * @summary - * @param {TokenRequest} tokenRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - token(tokenRequest: TokenRequest, options?: any): AxiosPromise { - return localVarFp.token(tokenRequest, options).then((request) => request(axios, basePath)); - }, - }; +export const AuthApiFactory = function ( + configuration?: Configuration, + basePath?: string, + axios?: AxiosInstance +) { + const localVarFp = AuthApiFp(configuration); + return { + /** + * リフレッシュトークンを元にアクセストークンを再生成します + * @summary + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + accessToken(options?: any): AxiosPromise { + return localVarFp + .accessToken(options) + .then((request) => request(axios, basePath)); + }, + /** + * AzureADB2Cでのサインイン後に払いだされるIDトークンを元に認証用のアクセストークンとリフレッシュトークンを生成します + * @summary + * @param {TokenRequest} tokenRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + token( + tokenRequest: TokenRequest, + options?: any + ): AxiosPromise { + return localVarFp + .token(tokenRequest, options) + .then((request) => request(axios, basePath)); + }, + }; }; /** @@ -2232,107 +2826,138 @@ export const AuthApiFactory = function (configuration?: Configuration, basePath? * @extends {BaseAPI} */ export class AuthApi extends BaseAPI { - /** - * リフレッシュトークンを元にアクセストークンを再生成します - * @summary - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof AuthApi - */ - public accessToken(options?: AxiosRequestConfig) { - return AuthApiFp(this.configuration).accessToken(options).then((request) => request(this.axios, this.basePath)); - } + /** + * リフレッシュトークンを元にアクセストークンを再生成します + * @summary + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof AuthApi + */ + public accessToken(options?: AxiosRequestConfig) { + return AuthApiFp(this.configuration) + .accessToken(options) + .then((request) => request(this.axios, this.basePath)); + } - /** - * AzureADB2Cでのサインイン後に払いだされるIDトークンを元に認証用のアクセストークンとリフレッシュトークンを生成します - * @summary - * @param {TokenRequest} tokenRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof AuthApi - */ - public token(tokenRequest: TokenRequest, options?: AxiosRequestConfig) { - return AuthApiFp(this.configuration).token(tokenRequest, options).then((request) => request(this.axios, this.basePath)); - } + /** + * AzureADB2Cでのサインイン後に払いだされるIDトークンを元に認証用のアクセストークンとリフレッシュトークンを生成します + * @summary + * @param {TokenRequest} tokenRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof AuthApi + */ + public token(tokenRequest: TokenRequest, options?: AxiosRequestConfig) { + return AuthApiFp(this.configuration) + .token(tokenRequest, options) + .then((request) => request(this.axios, this.basePath)); + } } - /** * DefaultApi - axios parameter creator * @export */ -export const DefaultApiAxiosParamCreator = function (configuration?: Configuration) { - return { - /** - * - * @summary - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - checkHealth: async (options: AxiosRequestConfig = {}): Promise => { - const localVarPath = `/health`; - // 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; - } +export const DefaultApiAxiosParamCreator = function ( + configuration?: Configuration +) { + return { + /** + * + * @summary + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + checkHealth: async ( + options: AxiosRequestConfig = {} + ): Promise => { + const localVarPath = `/health`; + // 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; + const localVarRequestOptions = { + method: "GET", + ...baseOptions, + ...options, + }; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = + baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = { + ...localVarHeaderParameter, + ...headersFromBaseOptions, + ...options.headers, + }; - - setSearchParams(localVarUrlObj, localVarQueryParameter); - let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; - localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; - - return { - url: toPathString(localVarUrlObj), - options: localVarRequestOptions, - }; - }, - } + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + }; }; /** * DefaultApi - functional programming interface * @export */ -export const DefaultApiFp = function(configuration?: Configuration) { - const localVarAxiosParamCreator = DefaultApiAxiosParamCreator(configuration) - return { - /** - * - * @summary - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - async checkHealth(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.checkHealth(options); - return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); - }, - } +export const DefaultApiFp = function (configuration?: Configuration) { + const localVarAxiosParamCreator = DefaultApiAxiosParamCreator(configuration); + return { + /** + * + * @summary + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async checkHealth( + options?: AxiosRequestConfig + ): Promise< + (axios?: AxiosInstance, basePath?: string) => AxiosPromise + > { + const localVarAxiosArgs = await localVarAxiosParamCreator.checkHealth( + options + ); + return createRequestFunction( + localVarAxiosArgs, + globalAxios, + BASE_PATH, + configuration + ); + }, + }; }; /** * DefaultApi - factory interface * @export */ -export const DefaultApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) { - const localVarFp = DefaultApiFp(configuration) - return { - /** - * - * @summary - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - checkHealth(options?: any): AxiosPromise { - return localVarFp.checkHealth(options).then((request) => request(axios, basePath)); - }, - }; +export const DefaultApiFactory = function ( + configuration?: Configuration, + basePath?: string, + axios?: AxiosInstance +) { + const localVarFp = DefaultApiFp(configuration); + return { + /** + * + * @summary + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + checkHealth(options?: any): AxiosPromise { + return localVarFp + .checkHealth(options) + .then((request) => request(axios, basePath)); + }, + }; }; /** @@ -2342,284 +2967,416 @@ export const DefaultApiFactory = function (configuration?: Configuration, basePa * @extends {BaseAPI} */ export class DefaultApi extends BaseAPI { - /** - * - * @summary - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof DefaultApi - */ - public checkHealth(options?: AxiosRequestConfig) { - return DefaultApiFp(this.configuration).checkHealth(options).then((request) => request(this.axios, this.basePath)); - } + /** + * + * @summary + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof DefaultApi + */ + public checkHealth(options?: AxiosRequestConfig) { + return DefaultApiFp(this.configuration) + .checkHealth(options) + .then((request) => request(this.axios, this.basePath)); + } } - /** * FilesApi - axios parameter creator * @export */ -export const FilesApiAxiosParamCreator = function (configuration?: Configuration) { - return { - /** - * 指定した音声ファイルのBlob Storage上のダウンロード先アクセスURLを取得します - * @summary - * @param {number} audioFileId ODMSCloud上で管理する音声ファイルのID - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - downloadLocation: async (audioFileId: number, options: AxiosRequestConfig = {}): Promise => { - // verify required parameter 'audioFileId' is not null or undefined - assertParamExists('downloadLocation', 'audioFileId', audioFileId) - const localVarPath = `/files/audio/download-location`; - // 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; - } +export const FilesApiAxiosParamCreator = function ( + configuration?: Configuration +) { + return { + /** + * 指定した音声ファイルのBlob Storage上のダウンロード先アクセスURLを取得します + * @summary + * @param {number} audioFileId ODMSCloud上で管理する音声ファイルのID + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + downloadLocation: async ( + audioFileId: number, + options: AxiosRequestConfig = {} + ): Promise => { + // verify required parameter 'audioFileId' is not null or undefined + assertParamExists("downloadLocation", "audioFileId", audioFileId); + const localVarPath = `/files/audio/download-location`; + // 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; + 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) + // authentication bearer required + // http bearer authentication required + await setBearerAuthToObject(localVarHeaderParameter, configuration); - if (audioFileId !== undefined) { - localVarQueryParameter['audioFileId'] = audioFileId; - } + if (audioFileId !== undefined) { + localVarQueryParameter["audioFileId"] = audioFileId; + } + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = + baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = { + ...localVarHeaderParameter, + ...headersFromBaseOptions, + ...options.headers, + }; - - setSearchParams(localVarUrlObj, localVarQueryParameter); - let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; - localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * 指定した音声ファイルに対応したテンプレートファイルのBlob Storage上のダウンロード先アクセスURLを取得します + * @summary + * @param {number} audioFileId 文字起こし対象の音声ファイルID + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + downloadTemplateLocation: async ( + audioFileId: number, + options: AxiosRequestConfig = {} + ): Promise => { + // verify required parameter 'audioFileId' is not null or undefined + assertParamExists("downloadTemplateLocation", "audioFileId", audioFileId); + const localVarPath = `/files/template/download-location`; + // 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; + } - return { - url: toPathString(localVarUrlObj), - options: localVarRequestOptions, - }; - }, - /** - * 指定した音声ファイルに対応したテンプレートファイルのBlob Storage上のダウンロード先アクセスURLを取得します - * @summary - * @param {number} audioFileId 文字起こし対象の音声ファイルID - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - downloadTemplateLocation: async (audioFileId: number, options: AxiosRequestConfig = {}): Promise => { - // verify required parameter 'audioFileId' is not null or undefined - assertParamExists('downloadTemplateLocation', 'audioFileId', audioFileId) - const localVarPath = `/files/template/download-location`; - // 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; - 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); - // authentication bearer required - // http bearer authentication required - await setBearerAuthToObject(localVarHeaderParameter, configuration) + if (audioFileId !== undefined) { + localVarQueryParameter["audioFileId"] = audioFileId; + } - if (audioFileId !== undefined) { - localVarQueryParameter['audioFileId'] = audioFileId; - } + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = + baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = { + ...localVarHeaderParameter, + ...headersFromBaseOptions, + ...options.headers, + }; + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * アップロードが完了した音声ファイルの情報を登録し、文字起こしタスクを生成します + * @summary + * @param {AudioUploadFinishedRequest} audioUploadFinishedRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + uploadFinished: async ( + audioUploadFinishedRequest: AudioUploadFinishedRequest, + options: AxiosRequestConfig = {} + ): Promise => { + // verify required parameter 'audioUploadFinishedRequest' is not null or undefined + assertParamExists( + "uploadFinished", + "audioUploadFinishedRequest", + audioUploadFinishedRequest + ); + const localVarPath = `/files/audio/upload-finished`; + // 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; + } - - setSearchParams(localVarUrlObj, localVarQueryParameter); - let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; - localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + const localVarRequestOptions = { + method: "POST", + ...baseOptions, + ...options, + }; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; - return { - url: toPathString(localVarUrlObj), - options: localVarRequestOptions, - }; - }, - /** - * アップロードが完了した音声ファイルの情報を登録し、文字起こしタスクを生成します - * @summary - * @param {AudioUploadFinishedRequest} audioUploadFinishedRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - uploadFinished: async (audioUploadFinishedRequest: AudioUploadFinishedRequest, options: AxiosRequestConfig = {}): Promise => { - // verify required parameter 'audioUploadFinishedRequest' is not null or undefined - assertParamExists('uploadFinished', 'audioUploadFinishedRequest', audioUploadFinishedRequest) - const localVarPath = `/files/audio/upload-finished`; - // 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; - } + // authentication bearer required + // http bearer authentication required + await setBearerAuthToObject(localVarHeaderParameter, configuration); - const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options}; - const localVarHeaderParameter = {} as any; - const localVarQueryParameter = {} as any; + localVarHeaderParameter["Content-Type"] = "application/json"; - // 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, + }; + localVarRequestOptions.data = serializeDataIfNeeded( + audioUploadFinishedRequest, + localVarRequestOptions, + configuration + ); + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * ログイン中ユーザー用のBlob Storage上の音声ファイルのアップロード先アクセスURLを取得します + * @summary + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + uploadLocation: async ( + options: AxiosRequestConfig = {} + ): Promise => { + const localVarPath = `/files/audio/upload-location`; + // 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; + } - - localVarHeaderParameter['Content-Type'] = 'application/json'; + const localVarRequestOptions = { + method: "GET", + ...baseOptions, + ...options, + }; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; - setSearchParams(localVarUrlObj, localVarQueryParameter); - let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; - localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; - localVarRequestOptions.data = serializeDataIfNeeded(audioUploadFinishedRequest, localVarRequestOptions, configuration) + // authentication bearer required + // http bearer authentication required + await setBearerAuthToObject(localVarHeaderParameter, configuration); - return { - url: toPathString(localVarUrlObj), - options: localVarRequestOptions, - }; - }, - /** - * ログイン中ユーザー用のBlob Storage上の音声ファイルのアップロード先アクセスURLを取得します - * @summary - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - uploadLocation: async (options: AxiosRequestConfig = {}): Promise => { - const localVarPath = `/files/audio/upload-location`; - // 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; - } + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = + baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = { + ...localVarHeaderParameter, + ...headersFromBaseOptions, + ...options.headers, + }; - 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, - }; - }, - } + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + }; }; /** * FilesApi - functional programming interface * @export */ -export const FilesApiFp = function(configuration?: Configuration) { - const localVarAxiosParamCreator = FilesApiAxiosParamCreator(configuration) - return { - /** - * 指定した音声ファイルのBlob Storage上のダウンロード先アクセスURLを取得します - * @summary - * @param {number} audioFileId ODMSCloud上で管理する音声ファイルのID - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - async downloadLocation(audioFileId: number, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.downloadLocation(audioFileId, options); - return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); - }, - /** - * 指定した音声ファイルに対応したテンプレートファイルのBlob Storage上のダウンロード先アクセスURLを取得します - * @summary - * @param {number} audioFileId 文字起こし対象の音声ファイルID - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - async downloadTemplateLocation(audioFileId: number, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.downloadTemplateLocation(audioFileId, options); - return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); - }, - /** - * アップロードが完了した音声ファイルの情報を登録し、文字起こしタスクを生成します - * @summary - * @param {AudioUploadFinishedRequest} audioUploadFinishedRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - async uploadFinished(audioUploadFinishedRequest: AudioUploadFinishedRequest, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.uploadFinished(audioUploadFinishedRequest, options); - return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); - }, - /** - * ログイン中ユーザー用のBlob Storage上の音声ファイルのアップロード先アクセスURLを取得します - * @summary - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - async uploadLocation(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.uploadLocation(options); - return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); - }, - } +export const FilesApiFp = function (configuration?: Configuration) { + const localVarAxiosParamCreator = FilesApiAxiosParamCreator(configuration); + return { + /** + * 指定した音声ファイルのBlob Storage上のダウンロード先アクセスURLを取得します + * @summary + * @param {number} audioFileId ODMSCloud上で管理する音声ファイルのID + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async downloadLocation( + audioFileId: number, + options?: AxiosRequestConfig + ): Promise< + ( + axios?: AxiosInstance, + basePath?: string + ) => AxiosPromise + > { + const localVarAxiosArgs = + await localVarAxiosParamCreator.downloadLocation(audioFileId, options); + return createRequestFunction( + localVarAxiosArgs, + globalAxios, + BASE_PATH, + configuration + ); + }, + /** + * 指定した音声ファイルに対応したテンプレートファイルのBlob Storage上のダウンロード先アクセスURLを取得します + * @summary + * @param {number} audioFileId 文字起こし対象の音声ファイルID + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async downloadTemplateLocation( + audioFileId: number, + options?: AxiosRequestConfig + ): Promise< + ( + axios?: AxiosInstance, + basePath?: string + ) => AxiosPromise + > { + const localVarAxiosArgs = + await localVarAxiosParamCreator.downloadTemplateLocation( + audioFileId, + options + ); + return createRequestFunction( + localVarAxiosArgs, + globalAxios, + BASE_PATH, + configuration + ); + }, + /** + * アップロードが完了した音声ファイルの情報を登録し、文字起こしタスクを生成します + * @summary + * @param {AudioUploadFinishedRequest} audioUploadFinishedRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async uploadFinished( + audioUploadFinishedRequest: AudioUploadFinishedRequest, + options?: AxiosRequestConfig + ): Promise< + ( + axios?: AxiosInstance, + basePath?: string + ) => AxiosPromise + > { + const localVarAxiosArgs = await localVarAxiosParamCreator.uploadFinished( + audioUploadFinishedRequest, + options + ); + return createRequestFunction( + localVarAxiosArgs, + globalAxios, + BASE_PATH, + configuration + ); + }, + /** + * ログイン中ユーザー用のBlob Storage上の音声ファイルのアップロード先アクセスURLを取得します + * @summary + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async uploadLocation( + options?: AxiosRequestConfig + ): Promise< + ( + axios?: AxiosInstance, + basePath?: string + ) => AxiosPromise + > { + const localVarAxiosArgs = await localVarAxiosParamCreator.uploadLocation( + options + ); + return createRequestFunction( + localVarAxiosArgs, + globalAxios, + BASE_PATH, + configuration + ); + }, + }; }; /** * FilesApi - factory interface * @export */ -export const FilesApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) { - const localVarFp = FilesApiFp(configuration) - return { - /** - * 指定した音声ファイルのBlob Storage上のダウンロード先アクセスURLを取得します - * @summary - * @param {number} audioFileId ODMSCloud上で管理する音声ファイルのID - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - downloadLocation(audioFileId: number, options?: any): AxiosPromise { - return localVarFp.downloadLocation(audioFileId, options).then((request) => request(axios, basePath)); - }, - /** - * 指定した音声ファイルに対応したテンプレートファイルのBlob Storage上のダウンロード先アクセスURLを取得します - * @summary - * @param {number} audioFileId 文字起こし対象の音声ファイルID - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - downloadTemplateLocation(audioFileId: number, options?: any): AxiosPromise { - return localVarFp.downloadTemplateLocation(audioFileId, options).then((request) => request(axios, basePath)); - }, - /** - * アップロードが完了した音声ファイルの情報を登録し、文字起こしタスクを生成します - * @summary - * @param {AudioUploadFinishedRequest} audioUploadFinishedRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - uploadFinished(audioUploadFinishedRequest: AudioUploadFinishedRequest, options?: any): AxiosPromise { - return localVarFp.uploadFinished(audioUploadFinishedRequest, options).then((request) => request(axios, basePath)); - }, - /** - * ログイン中ユーザー用のBlob Storage上の音声ファイルのアップロード先アクセスURLを取得します - * @summary - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - uploadLocation(options?: any): AxiosPromise { - return localVarFp.uploadLocation(options).then((request) => request(axios, basePath)); - }, - }; +export const FilesApiFactory = function ( + configuration?: Configuration, + basePath?: string, + axios?: AxiosInstance +) { + const localVarFp = FilesApiFp(configuration); + return { + /** + * 指定した音声ファイルのBlob Storage上のダウンロード先アクセスURLを取得します + * @summary + * @param {number} audioFileId ODMSCloud上で管理する音声ファイルのID + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + downloadLocation( + audioFileId: number, + options?: any + ): AxiosPromise { + return localVarFp + .downloadLocation(audioFileId, options) + .then((request) => request(axios, basePath)); + }, + /** + * 指定した音声ファイルに対応したテンプレートファイルのBlob Storage上のダウンロード先アクセスURLを取得します + * @summary + * @param {number} audioFileId 文字起こし対象の音声ファイルID + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + downloadTemplateLocation( + audioFileId: number, + options?: any + ): AxiosPromise { + return localVarFp + .downloadTemplateLocation(audioFileId, options) + .then((request) => request(axios, basePath)); + }, + /** + * アップロードが完了した音声ファイルの情報を登録し、文字起こしタスクを生成します + * @summary + * @param {AudioUploadFinishedRequest} audioUploadFinishedRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + uploadFinished( + audioUploadFinishedRequest: AudioUploadFinishedRequest, + options?: any + ): AxiosPromise { + return localVarFp + .uploadFinished(audioUploadFinishedRequest, options) + .then((request) => request(axios, basePath)); + }, + /** + * ログイン中ユーザー用のBlob Storage上の音声ファイルのアップロード先アクセスURLを取得します + * @summary + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + uploadLocation(options?: any): AxiosPromise { + return localVarFp + .uploadLocation(options) + .then((request) => request(axios, basePath)); + }, + }; }; /** @@ -2629,265 +3386,482 @@ export const FilesApiFactory = function (configuration?: Configuration, basePath * @extends {BaseAPI} */ export class FilesApi extends BaseAPI { - /** - * 指定した音声ファイルのBlob Storage上のダウンロード先アクセスURLを取得します - * @summary - * @param {number} audioFileId ODMSCloud上で管理する音声ファイルのID - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof FilesApi - */ - public downloadLocation(audioFileId: number, options?: AxiosRequestConfig) { - return FilesApiFp(this.configuration).downloadLocation(audioFileId, options).then((request) => request(this.axios, this.basePath)); - } + /** + * 指定した音声ファイルのBlob Storage上のダウンロード先アクセスURLを取得します + * @summary + * @param {number} audioFileId ODMSCloud上で管理する音声ファイルのID + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof FilesApi + */ + public downloadLocation(audioFileId: number, options?: AxiosRequestConfig) { + return FilesApiFp(this.configuration) + .downloadLocation(audioFileId, options) + .then((request) => request(this.axios, this.basePath)); + } - /** - * 指定した音声ファイルに対応したテンプレートファイルのBlob Storage上のダウンロード先アクセスURLを取得します - * @summary - * @param {number} audioFileId 文字起こし対象の音声ファイルID - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof FilesApi - */ - public downloadTemplateLocation(audioFileId: number, options?: AxiosRequestConfig) { - return FilesApiFp(this.configuration).downloadTemplateLocation(audioFileId, options).then((request) => request(this.axios, this.basePath)); - } + /** + * 指定した音声ファイルに対応したテンプレートファイルのBlob Storage上のダウンロード先アクセスURLを取得します + * @summary + * @param {number} audioFileId 文字起こし対象の音声ファイルID + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof FilesApi + */ + public downloadTemplateLocation( + audioFileId: number, + options?: AxiosRequestConfig + ) { + return FilesApiFp(this.configuration) + .downloadTemplateLocation(audioFileId, options) + .then((request) => request(this.axios, this.basePath)); + } - /** - * アップロードが完了した音声ファイルの情報を登録し、文字起こしタスクを生成します - * @summary - * @param {AudioUploadFinishedRequest} audioUploadFinishedRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof FilesApi - */ - public uploadFinished(audioUploadFinishedRequest: AudioUploadFinishedRequest, options?: AxiosRequestConfig) { - return FilesApiFp(this.configuration).uploadFinished(audioUploadFinishedRequest, options).then((request) => request(this.axios, this.basePath)); - } + /** + * アップロードが完了した音声ファイルの情報を登録し、文字起こしタスクを生成します + * @summary + * @param {AudioUploadFinishedRequest} audioUploadFinishedRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof FilesApi + */ + public uploadFinished( + audioUploadFinishedRequest: AudioUploadFinishedRequest, + options?: AxiosRequestConfig + ) { + return FilesApiFp(this.configuration) + .uploadFinished(audioUploadFinishedRequest, options) + .then((request) => request(this.axios, this.basePath)); + } - /** - * ログイン中ユーザー用のBlob Storage上の音声ファイルのアップロード先アクセスURLを取得します - * @summary - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof FilesApi - */ - public uploadLocation(options?: AxiosRequestConfig) { - return FilesApiFp(this.configuration).uploadLocation(options).then((request) => request(this.axios, this.basePath)); - } + /** + * ログイン中ユーザー用のBlob Storage上の音声ファイルのアップロード先アクセスURLを取得します + * @summary + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof FilesApi + */ + public uploadLocation(options?: AxiosRequestConfig) { + return FilesApiFp(this.configuration) + .uploadLocation(options) + .then((request) => request(this.axios, this.basePath)); + } } - /** * LicensesApi - axios parameter creator * @export */ -export const LicensesApiAxiosParamCreator = function (configuration?: Configuration) { - return { - /** - * - * @summary - * @param {ActivateCardLicensesRequest} activateCardLicensesRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - activateCardLicenses: async (activateCardLicensesRequest: ActivateCardLicensesRequest, options: AxiosRequestConfig = {}): Promise => { - // verify required parameter 'activateCardLicensesRequest' is not null or undefined - assertParamExists('activateCardLicenses', 'activateCardLicensesRequest', activateCardLicensesRequest) - const localVarPath = `/licenses/cards/activate`; - // 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; - } +export const LicensesApiAxiosParamCreator = function ( + configuration?: Configuration +) { + return { + /** + * + * @summary + * @param {ActivateCardLicensesRequest} activateCardLicensesRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + activateCardLicenses: async ( + activateCardLicensesRequest: ActivateCardLicensesRequest, + options: AxiosRequestConfig = {} + ): Promise => { + // verify required parameter 'activateCardLicensesRequest' is not null or undefined + assertParamExists( + "activateCardLicenses", + "activateCardLicensesRequest", + activateCardLicensesRequest + ); + const localVarPath = `/licenses/cards/activate`; + // 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; + 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) + // authentication bearer required + // http bearer authentication required + await setBearerAuthToObject(localVarHeaderParameter, configuration); + localVarHeaderParameter["Content-Type"] = "application/json"; - - localVarHeaderParameter['Content-Type'] = 'application/json'; + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = + baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = { + ...localVarHeaderParameter, + ...headersFromBaseOptions, + ...options.headers, + }; + localVarRequestOptions.data = serializeDataIfNeeded( + activateCardLicensesRequest, + localVarRequestOptions, + configuration + ); - setSearchParams(localVarUrlObj, localVarQueryParameter); - let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; - localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; - localVarRequestOptions.data = serializeDataIfNeeded(activateCardLicensesRequest, localVarRequestOptions, configuration) + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * + * @summary + * @param {CreateOrdersRequest} createOrdersRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + createOrders: async ( + createOrdersRequest: CreateOrdersRequest, + options: AxiosRequestConfig = {} + ): Promise => { + // verify required parameter 'createOrdersRequest' is not null or undefined + assertParamExists( + "createOrders", + "createOrdersRequest", + createOrdersRequest + ); + const localVarPath = `/licenses/orders`; + // 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; + } - return { - url: toPathString(localVarUrlObj), - options: localVarRequestOptions, - }; - }, - /** - * - * @summary - * @param {CreateOrdersRequest} createOrdersRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - createOrders: async (createOrdersRequest: CreateOrdersRequest, options: AxiosRequestConfig = {}): Promise => { - // verify required parameter 'createOrdersRequest' is not null or undefined - assertParamExists('createOrders', 'createOrdersRequest', createOrdersRequest) - const localVarPath = `/licenses/orders`; - // 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; - 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); - // 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( + createOrdersRequest, + localVarRequestOptions, + configuration + ); - - localVarHeaderParameter['Content-Type'] = 'application/json'; + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * 割り当て可能なライセンスを取得します + * @summary + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getAllocatableLicenses: async ( + options: AxiosRequestConfig = {} + ): Promise => { + const localVarPath = `/licenses/allocatable`; + // 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; + } - setSearchParams(localVarUrlObj, localVarQueryParameter); - let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; - localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; - localVarRequestOptions.data = serializeDataIfNeeded(createOrdersRequest, localVarRequestOptions, configuration) + const localVarRequestOptions = { + method: "GET", + ...baseOptions, + ...options, + }; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; - return { - url: toPathString(localVarUrlObj), - options: localVarRequestOptions, - }; - }, - /** - * - * @summary - * @param {IssueCardLicensesRequest} issueCardLicensesRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - issueCardLicenses: async (issueCardLicensesRequest: IssueCardLicensesRequest, options: AxiosRequestConfig = {}): Promise => { - // verify required parameter 'issueCardLicensesRequest' is not null or undefined - assertParamExists('issueCardLicenses', 'issueCardLicensesRequest', issueCardLicensesRequest) - const localVarPath = `/licenses/cards`; - // 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; - } + // authentication bearer required + // http bearer authentication required + await setBearerAuthToObject(localVarHeaderParameter, configuration); - const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options}; - const localVarHeaderParameter = {} as any; - const localVarQueryParameter = {} as any; + localVarHeaderParameter["Content-Type"] = "application/json"; - // 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, + }; + localVarRequestOptions.data = serializeDataIfNeeded( + localVarRequestOptions, + configuration + ); + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * + * @summary + * @param {IssueCardLicensesRequest} issueCardLicensesRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + issueCardLicenses: async ( + issueCardLicensesRequest: IssueCardLicensesRequest, + options: AxiosRequestConfig = {} + ): Promise => { + // verify required parameter 'issueCardLicensesRequest' is not null or undefined + assertParamExists( + "issueCardLicenses", + "issueCardLicensesRequest", + issueCardLicensesRequest + ); + const localVarPath = `/licenses/cards`; + // 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; + } - - localVarHeaderParameter['Content-Type'] = 'application/json'; + const localVarRequestOptions = { + method: "POST", + ...baseOptions, + ...options, + }; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; - setSearchParams(localVarUrlObj, localVarQueryParameter); - let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; - localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; - localVarRequestOptions.data = serializeDataIfNeeded(issueCardLicensesRequest, localVarRequestOptions, configuration) + // authentication bearer required + // http bearer authentication required + await setBearerAuthToObject(localVarHeaderParameter, configuration); - return { - url: toPathString(localVarUrlObj), - options: localVarRequestOptions, - }; - }, - } + localVarHeaderParameter["Content-Type"] = "application/json"; + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = + baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = { + ...localVarHeaderParameter, + ...headersFromBaseOptions, + ...options.headers, + }; + localVarRequestOptions.data = serializeDataIfNeeded( + issueCardLicensesRequest, + localVarRequestOptions, + configuration + ); + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + }; }; /** * LicensesApi - functional programming interface * @export */ -export const LicensesApiFp = function(configuration?: Configuration) { - const localVarAxiosParamCreator = LicensesApiAxiosParamCreator(configuration) - return { - /** - * - * @summary - * @param {ActivateCardLicensesRequest} activateCardLicensesRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - async activateCardLicenses(activateCardLicensesRequest: ActivateCardLicensesRequest, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.activateCardLicenses(activateCardLicensesRequest, options); - return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); - }, - /** - * - * @summary - * @param {CreateOrdersRequest} createOrdersRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - async createOrders(createOrdersRequest: CreateOrdersRequest, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.createOrders(createOrdersRequest, options); - return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); - }, - /** - * - * @summary - * @param {IssueCardLicensesRequest} issueCardLicensesRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - async issueCardLicenses(issueCardLicensesRequest: IssueCardLicensesRequest, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.issueCardLicenses(issueCardLicensesRequest, options); - return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); - }, - } +export const LicensesApiFp = function (configuration?: Configuration) { + const localVarAxiosParamCreator = LicensesApiAxiosParamCreator(configuration); + return { + /** + * + * @summary + * @param {ActivateCardLicensesRequest} activateCardLicensesRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async activateCardLicenses( + activateCardLicensesRequest: ActivateCardLicensesRequest, + options?: AxiosRequestConfig + ): Promise< + (axios?: AxiosInstance, basePath?: string) => AxiosPromise + > { + const localVarAxiosArgs = + await localVarAxiosParamCreator.activateCardLicenses( + activateCardLicensesRequest, + options + ); + return createRequestFunction( + localVarAxiosArgs, + globalAxios, + BASE_PATH, + configuration + ); + }, + /** + * + * @summary + * @param {CreateOrdersRequest} createOrdersRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async createOrders( + createOrdersRequest: CreateOrdersRequest, + options?: AxiosRequestConfig + ): Promise< + (axios?: AxiosInstance, basePath?: string) => AxiosPromise + > { + const localVarAxiosArgs = await localVarAxiosParamCreator.createOrders( + createOrdersRequest, + options + ); + return createRequestFunction( + localVarAxiosArgs, + globalAxios, + BASE_PATH, + configuration + ); + }, + /** + * 割り当て可能なライセンスを取得します + * @summary + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async getAllocatableLicenses( + options?: AxiosRequestConfig + ): Promise< + ( + axios?: AxiosInstance, + basePath?: string + ) => AxiosPromise + > { + const localVarAxiosArgs = + await localVarAxiosParamCreator.getAllocatableLicenses(options); + return createRequestFunction( + localVarAxiosArgs, + globalAxios, + BASE_PATH, + configuration + ); + }, + /** + * + * @summary + * @param {IssueCardLicensesRequest} issueCardLicensesRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async issueCardLicenses( + issueCardLicensesRequest: IssueCardLicensesRequest, + options?: AxiosRequestConfig + ): Promise< + ( + axios?: AxiosInstance, + basePath?: string + ) => AxiosPromise + > { + const localVarAxiosArgs = + await localVarAxiosParamCreator.issueCardLicenses( + issueCardLicensesRequest, + options + ); + return createRequestFunction( + localVarAxiosArgs, + globalAxios, + BASE_PATH, + configuration + ); + }, + }; }; /** * LicensesApi - factory interface * @export */ -export const LicensesApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) { - const localVarFp = LicensesApiFp(configuration) - return { - /** - * - * @summary - * @param {ActivateCardLicensesRequest} activateCardLicensesRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - activateCardLicenses(activateCardLicensesRequest: ActivateCardLicensesRequest, options?: any): AxiosPromise { - return localVarFp.activateCardLicenses(activateCardLicensesRequest, options).then((request) => request(axios, basePath)); - }, - /** - * - * @summary - * @param {CreateOrdersRequest} createOrdersRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - createOrders(createOrdersRequest: CreateOrdersRequest, options?: any): AxiosPromise { - return localVarFp.createOrders(createOrdersRequest, options).then((request) => request(axios, basePath)); - }, - /** - * - * @summary - * @param {IssueCardLicensesRequest} issueCardLicensesRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - issueCardLicenses(issueCardLicensesRequest: IssueCardLicensesRequest, options?: any): AxiosPromise { - return localVarFp.issueCardLicenses(issueCardLicensesRequest, options).then((request) => request(axios, basePath)); - }, - }; +export const LicensesApiFactory = function ( + configuration?: Configuration, + basePath?: string, + axios?: AxiosInstance +) { + const localVarFp = LicensesApiFp(configuration); + return { + /** + * + * @summary + * @param {ActivateCardLicensesRequest} activateCardLicensesRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + activateCardLicenses( + activateCardLicensesRequest: ActivateCardLicensesRequest, + options?: any + ): AxiosPromise { + return localVarFp + .activateCardLicenses(activateCardLicensesRequest, options) + .then((request) => request(axios, basePath)); + }, + /** + * + * @summary + * @param {CreateOrdersRequest} createOrdersRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + createOrders( + createOrdersRequest: CreateOrdersRequest, + options?: any + ): AxiosPromise { + return localVarFp + .createOrders(createOrdersRequest, options) + .then((request) => request(axios, basePath)); + }, + /** + * 割り当て可能なライセンスを取得します + * @summary + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getAllocatableLicenses( + options?: any + ): AxiosPromise { + return localVarFp + .getAllocatableLicenses(options) + .then((request) => request(axios, basePath)); + }, + /** + * + * @summary + * @param {IssueCardLicensesRequest} issueCardLicensesRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + issueCardLicenses( + issueCardLicensesRequest: IssueCardLicensesRequest, + options?: any + ): AxiosPromise { + return localVarFp + .issueCardLicenses(issueCardLicensesRequest, options) + .then((request) => request(axios, basePath)); + }, + }; }; /** @@ -2897,132 +3871,198 @@ export const LicensesApiFactory = function (configuration?: Configuration, baseP * @extends {BaseAPI} */ export class LicensesApi extends BaseAPI { - /** - * - * @summary - * @param {ActivateCardLicensesRequest} activateCardLicensesRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof LicensesApi - */ - public activateCardLicenses(activateCardLicensesRequest: ActivateCardLicensesRequest, options?: AxiosRequestConfig) { - return LicensesApiFp(this.configuration).activateCardLicenses(activateCardLicensesRequest, options).then((request) => request(this.axios, this.basePath)); - } + /** + * + * @summary + * @param {ActivateCardLicensesRequest} activateCardLicensesRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof LicensesApi + */ + public activateCardLicenses( + activateCardLicensesRequest: ActivateCardLicensesRequest, + options?: AxiosRequestConfig + ) { + return LicensesApiFp(this.configuration) + .activateCardLicenses(activateCardLicensesRequest, options) + .then((request) => request(this.axios, this.basePath)); + } - /** - * - * @summary - * @param {CreateOrdersRequest} createOrdersRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof LicensesApi - */ - public createOrders(createOrdersRequest: CreateOrdersRequest, options?: AxiosRequestConfig) { - return LicensesApiFp(this.configuration).createOrders(createOrdersRequest, options).then((request) => request(this.axios, this.basePath)); - } + /** + * + * @summary + * @param {CreateOrdersRequest} createOrdersRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof LicensesApi + */ + public createOrders( + createOrdersRequest: CreateOrdersRequest, + options?: AxiosRequestConfig + ) { + return LicensesApiFp(this.configuration) + .createOrders(createOrdersRequest, options) + .then((request) => request(this.axios, this.basePath)); + } - /** - * - * @summary - * @param {IssueCardLicensesRequest} issueCardLicensesRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof LicensesApi - */ - public issueCardLicenses(issueCardLicensesRequest: IssueCardLicensesRequest, options?: AxiosRequestConfig) { - return LicensesApiFp(this.configuration).issueCardLicenses(issueCardLicensesRequest, options).then((request) => request(this.axios, this.basePath)); - } + /** + * 割り当て可能なライセンスを取得します + * @summary + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof LicensesApi + */ + public getAllocatableLicenses(options?: AxiosRequestConfig) { + return LicensesApiFp(this.configuration) + .getAllocatableLicenses(options) + .then((request) => request(this.axios, this.basePath)); + } + + /** + * + * @summary + * @param {IssueCardLicensesRequest} issueCardLicensesRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof LicensesApi + */ + public issueCardLicenses( + issueCardLicensesRequest: IssueCardLicensesRequest, + options?: AxiosRequestConfig + ) { + return LicensesApiFp(this.configuration) + .issueCardLicenses(issueCardLicensesRequest, options) + .then((request) => request(this.axios, this.basePath)); + } } - /** * NotificationApi - axios parameter creator * @export */ -export const NotificationApiAxiosParamCreator = function (configuration?: Configuration) { - return { - /** - * - * @summary - * @param {RegisterRequest} registerRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - register: async (registerRequest: RegisterRequest, options: AxiosRequestConfig = {}): Promise => { - // verify required parameter 'registerRequest' is not null or undefined - assertParamExists('register', 'registerRequest', registerRequest) - const localVarPath = `/notification/register`; - // 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; - } +export const NotificationApiAxiosParamCreator = function ( + configuration?: Configuration +) { + return { + /** + * + * @summary + * @param {RegisterRequest} registerRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + register: async ( + registerRequest: RegisterRequest, + options: AxiosRequestConfig = {} + ): Promise => { + // verify required parameter 'registerRequest' is not null or undefined + assertParamExists("register", "registerRequest", registerRequest); + const localVarPath = `/notification/register`; + // 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; + 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) + // authentication bearer required + // http bearer authentication required + await setBearerAuthToObject(localVarHeaderParameter, configuration); + localVarHeaderParameter["Content-Type"] = "application/json"; - - localVarHeaderParameter['Content-Type'] = 'application/json'; + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = + baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = { + ...localVarHeaderParameter, + ...headersFromBaseOptions, + ...options.headers, + }; + localVarRequestOptions.data = serializeDataIfNeeded( + registerRequest, + localVarRequestOptions, + configuration + ); - setSearchParams(localVarUrlObj, localVarQueryParameter); - let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; - localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; - localVarRequestOptions.data = serializeDataIfNeeded(registerRequest, localVarRequestOptions, configuration) - - return { - url: toPathString(localVarUrlObj), - options: localVarRequestOptions, - }; - }, - } + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + }; }; /** * NotificationApi - functional programming interface * @export */ -export const NotificationApiFp = function(configuration?: Configuration) { - const localVarAxiosParamCreator = NotificationApiAxiosParamCreator(configuration) - return { - /** - * - * @summary - * @param {RegisterRequest} registerRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - async register(registerRequest: RegisterRequest, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.register(registerRequest, options); - return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); - }, - } +export const NotificationApiFp = function (configuration?: Configuration) { + const localVarAxiosParamCreator = + NotificationApiAxiosParamCreator(configuration); + return { + /** + * + * @summary + * @param {RegisterRequest} registerRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async register( + registerRequest: RegisterRequest, + options?: AxiosRequestConfig + ): Promise< + (axios?: AxiosInstance, basePath?: string) => AxiosPromise + > { + const localVarAxiosArgs = await localVarAxiosParamCreator.register( + registerRequest, + options + ); + return createRequestFunction( + localVarAxiosArgs, + globalAxios, + BASE_PATH, + configuration + ); + }, + }; }; /** * NotificationApi - factory interface * @export */ -export const NotificationApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) { - const localVarFp = NotificationApiFp(configuration) - return { - /** - * - * @summary - * @param {RegisterRequest} registerRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - register(registerRequest: RegisterRequest, options?: any): AxiosPromise { - return localVarFp.register(registerRequest, options).then((request) => request(axios, basePath)); - }, - }; +export const NotificationApiFactory = function ( + configuration?: Configuration, + basePath?: string, + axios?: AxiosInstance +) { + const localVarFp = NotificationApiFp(configuration); + return { + /** + * + * @summary + * @param {RegisterRequest} registerRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + register( + registerRequest: RegisterRequest, + options?: any + ): AxiosPromise { + return localVarFp + .register(registerRequest, options) + .then((request) => request(axios, basePath)); + }, + }; }; /** @@ -3032,618 +4072,910 @@ export const NotificationApiFactory = function (configuration?: Configuration, b * @extends {BaseAPI} */ export class NotificationApi extends BaseAPI { - /** - * - * @summary - * @param {RegisterRequest} registerRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof NotificationApi - */ - public register(registerRequest: RegisterRequest, options?: AxiosRequestConfig) { - return NotificationApiFp(this.configuration).register(registerRequest, options).then((request) => request(this.axios, this.basePath)); - } + /** + * + * @summary + * @param {RegisterRequest} registerRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof NotificationApi + */ + public register( + registerRequest: RegisterRequest, + options?: AxiosRequestConfig + ) { + return NotificationApiFp(this.configuration) + .register(registerRequest, options) + .then((request) => request(this.axios, this.basePath)); + } } - /** * TasksApi - axios parameter creator * @export */ -export const TasksApiAxiosParamCreator = function (configuration?: Configuration) { - return { - /** - * 指定した文字起こしタスクをバックアップします(ステータスをBackupにします) - * @summary - * @param {number} audioFileId ODMS Cloud上の音声ファイルID - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - backup: async (audioFileId: number, options: AxiosRequestConfig = {}): Promise => { - // verify required parameter 'audioFileId' is not null or undefined - assertParamExists('backup', 'audioFileId', audioFileId) - const localVarPath = `/tasks/{audioFileId}/backup` - .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; - } +export const TasksApiAxiosParamCreator = function ( + configuration?: Configuration +) { + return { + /** + * 指定した文字起こしタスクをバックアップします(ステータスをBackupにします) + * @summary + * @param {number} audioFileId ODMS Cloud上の音声ファイルID + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + backup: async ( + audioFileId: number, + options: AxiosRequestConfig = {} + ): Promise => { + // verify required parameter 'audioFileId' is not null or undefined + assertParamExists("backup", "audioFileId", audioFileId); + const localVarPath = `/tasks/{audioFileId}/backup`.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; + 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) + // 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, + }; - - setSearchParams(localVarUrlObj, localVarQueryParameter); - let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; - localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * 指定した文字起こしタスクをキャンセルします(ステータスをUploadedにします) + * @summary + * @param {number} audioFileId ODMS Cloud上の音声ファイルID + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + cancel: async ( + audioFileId: number, + options: AxiosRequestConfig = {} + ): Promise => { + // verify required parameter 'audioFileId' is not null or undefined + assertParamExists("cancel", "audioFileId", audioFileId); + const localVarPath = `/tasks/{audioFileId}/cancel`.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; + } - return { - url: toPathString(localVarUrlObj), - options: localVarRequestOptions, - }; - }, - /** - * 指定した文字起こしタスクをキャンセルします(ステータスをUploadedにします) - * @summary - * @param {number} audioFileId ODMS Cloud上の音声ファイルID - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - cancel: async (audioFileId: number, options: AxiosRequestConfig = {}): Promise => { - // verify required parameter 'audioFileId' is not null or undefined - assertParamExists('cancel', 'audioFileId', audioFileId) - const localVarPath = `/tasks/{audioFileId}/cancel` - .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; - 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); - // 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 {number} audioFileId ODMS Cloud上の音声ファイルID + * @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; + } - - setSearchParams(localVarUrlObj, localVarQueryParameter); - let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; - localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + const localVarRequestOptions = { + method: "POST", + ...baseOptions, + ...options, + }; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; - return { - url: toPathString(localVarUrlObj), - options: localVarRequestOptions, - }; - }, - /** - * 指定した文字起こしタスクのチェックアウト候補を変更します。 - * @summary - * @param {number} audioFileId ODMS Cloud上の音声ファイルID - * @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; - } + // authentication bearer required + // http bearer authentication required + await setBearerAuthToObject(localVarHeaderParameter, configuration); - const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options}; - const localVarHeaderParameter = {} as any; - const localVarQueryParameter = {} as any; + localVarHeaderParameter["Content-Type"] = "application/json"; - // 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, + }; + localVarRequestOptions.data = serializeDataIfNeeded( + postCheckoutPermissionRequest, + localVarRequestOptions, + configuration + ); + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * 指定した文字起こしタスクをチェックインします(ステータスをFinishedにします) + * @summary + * @param {number} audioFileId ODMS Cloud上の音声ファイルID + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + checkin: async ( + audioFileId: number, + options: AxiosRequestConfig = {} + ): Promise => { + // verify required parameter 'audioFileId' is not null or undefined + assertParamExists("checkin", "audioFileId", audioFileId); + const localVarPath = `/tasks/{audioFileId}/checkin`.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; + } - - localVarHeaderParameter['Content-Type'] = 'application/json'; + const localVarRequestOptions = { + method: "POST", + ...baseOptions, + ...options, + }; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; - setSearchParams(localVarUrlObj, localVarQueryParameter); - let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; - localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; - localVarRequestOptions.data = serializeDataIfNeeded(postCheckoutPermissionRequest, localVarRequestOptions, configuration) + // authentication bearer required + // http bearer authentication required + await setBearerAuthToObject(localVarHeaderParameter, configuration); - return { - url: toPathString(localVarUrlObj), - options: localVarRequestOptions, - }; - }, - /** - * 指定した文字起こしタスクをチェックインします(ステータスをFinishedにします) - * @summary - * @param {number} audioFileId ODMS Cloud上の音声ファイルID - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - checkin: async (audioFileId: number, options: AxiosRequestConfig = {}): Promise => { - // verify required parameter 'audioFileId' is not null or undefined - assertParamExists('checkin', 'audioFileId', audioFileId) - const localVarPath = `/tasks/{audioFileId}/checkin` - .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; - } + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = + baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = { + ...localVarHeaderParameter, + ...headersFromBaseOptions, + ...options.headers, + }; - const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options}; - const localVarHeaderParameter = {} as any; - const localVarQueryParameter = {} as any; + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * 指定した文字起こしタスクをチェックアウトします(ステータスをInprogressにします) + * @summary + * @param {number} audioFileId ODMS Cloud上の音声ファイルID + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + checkout: async ( + audioFileId: number, + options: AxiosRequestConfig = {} + ): Promise => { + // verify required parameter 'audioFileId' is not null or undefined + assertParamExists("checkout", "audioFileId", audioFileId); + const localVarPath = `/tasks/{audioFileId}/checkout`.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; + } - // authentication bearer required - // http bearer authentication required - await setBearerAuthToObject(localVarHeaderParameter, configuration) + 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); - - setSearchParams(localVarUrlObj, localVarQueryParameter); - let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; - localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = + baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = { + ...localVarHeaderParameter, + ...headersFromBaseOptions, + ...options.headers, + }; - return { - url: toPathString(localVarUrlObj), - options: localVarRequestOptions, - }; - }, - /** - * 指定した文字起こしタスクをチェックアウトします(ステータスをInprogressにします) - * @summary - * @param {number} audioFileId ODMS Cloud上の音声ファイルID - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - checkout: async (audioFileId: number, options: AxiosRequestConfig = {}): Promise => { - // verify required parameter 'audioFileId' is not null or undefined - assertParamExists('checkout', 'audioFileId', audioFileId) - const localVarPath = `/tasks/{audioFileId}/checkout` - .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; - } + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * 指定した文字起こしタスクの次のタスクに紐づく音声ファイルIDを取得します + * @summary + * @param {number} endedFileId 文字起こし完了したタスクの音声ファイルID + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getNextAudioFile: async ( + endedFileId: number, + options: AxiosRequestConfig = {} + ): Promise => { + // verify required parameter 'endedFileId' is not null or undefined + assertParamExists("getNextAudioFile", "endedFileId", endedFileId); + const localVarPath = `/tasks/next`; + // 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; + 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) + // authentication bearer required + // http bearer authentication required + await setBearerAuthToObject(localVarHeaderParameter, configuration); + if (endedFileId !== undefined) { + localVarQueryParameter["endedFileId"] = endedFileId; + } - - setSearchParams(localVarUrlObj, localVarQueryParameter); - let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; - localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = + baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = { + ...localVarHeaderParameter, + ...headersFromBaseOptions, + ...options.headers, + }; - return { - url: toPathString(localVarUrlObj), - options: localVarRequestOptions, - }; - }, - /** - * 指定した文字起こしタスクの次のタスクに紐づく音声ファイルIDを取得します - * @summary - * @param {number} endedFileId 文字起こし完了したタスクの音声ファイルID - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - getNextAudioFile: async (endedFileId: number, options: AxiosRequestConfig = {}): Promise => { - // verify required parameter 'endedFileId' is not null or undefined - assertParamExists('getNextAudioFile', 'endedFileId', endedFileId) - const localVarPath = `/tasks/next`; - // 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; - } + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * 音声ファイル・文字起こしタスク情報をページ指定して取得します + * @summary + * @param {number} [limit] タスクの取得件数(指定しない場合はデフォルト値) + * @param {number} [offset] オフセット(何件目から取得するか 設定しない場合はデフォルト値) + * @param {string} [status] 取得対象とするタスクのステータス。カンマ(,)区切りで複数指定可能。設定されない場合はすべてのステータスを取得対象とする。許容するステータスの値は次の通り: Uploaded / Pending / InProgress / Finished / Backup + * @param {string} [direction] ASC/DESC + * @param {string} [paramName] JOB_NUMBER/STATUS/ENCRYPTION/AUTHOR_ID/WORK_TYPE/FILE_NAME/FILE_LENGTH/FILE_SIZE/RECORDING_STARTED_DATE/RECORDING_FINISHED_DATE/UPLOAD_DATE/TRANSCRIPTION_STARTED_DATE/TRANSCRIPTION_FINISHED_DATE + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getTasks: async ( + limit?: number, + offset?: number, + status?: string, + direction?: string, + paramName?: string, + options: AxiosRequestConfig = {} + ): Promise => { + const localVarPath = `/tasks`; + // 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; + 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) + // authentication bearer required + // http bearer authentication required + await setBearerAuthToObject(localVarHeaderParameter, configuration); - if (endedFileId !== undefined) { - localVarQueryParameter['endedFileId'] = endedFileId; - } + if (limit !== undefined) { + localVarQueryParameter["limit"] = limit; + } + if (offset !== undefined) { + localVarQueryParameter["offset"] = offset; + } - - setSearchParams(localVarUrlObj, localVarQueryParameter); - let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; - localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + if (status !== undefined) { + localVarQueryParameter["status"] = status; + } - return { - url: toPathString(localVarUrlObj), - options: localVarRequestOptions, - }; - }, - /** - * 音声ファイル・文字起こしタスク情報をページ指定して取得します - * @summary - * @param {number} [limit] タスクの取得件数(指定しない場合はデフォルト値) - * @param {number} [offset] オフセット(何件目から取得するか 設定しない場合はデフォルト値) - * @param {string} [status] 取得対象とするタスクのステータス。カンマ(,)区切りで複数指定可能。設定されない場合はすべてのステータスを取得対象とする。許容するステータスの値は次の通り: Uploaded / Pending / InProgress / Finished / Backup - * @param {string} [direction] ASC/DESC - * @param {string} [paramName] JOB_NUMBER/STATUS/ENCRYPTION/AUTHOR_ID/WORK_TYPE/FILE_NAME/FILE_LENGTH/FILE_SIZE/RECORDING_STARTED_DATE/RECORDING_FINISHED_DATE/UPLOAD_DATE/TRANSCRIPTION_STARTED_DATE/TRANSCRIPTION_FINISHED_DATE - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - getTasks: async (limit?: number, offset?: number, status?: string, direction?: string, paramName?: string, options: AxiosRequestConfig = {}): Promise => { - const localVarPath = `/tasks`; - // 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; - } + if (direction !== undefined) { + localVarQueryParameter["direction"] = direction; + } - const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; - const localVarHeaderParameter = {} as any; - const localVarQueryParameter = {} as any; + if (paramName !== undefined) { + localVarQueryParameter["paramName"] = paramName; + } - // 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, + }; - if (limit !== undefined) { - localVarQueryParameter['limit'] = limit; - } + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * 指定した文字起こしタスクを差し戻します(ステータスをPendingにします) + * @summary + * @param {number} audioFileId ODMS Cloud上の音声ファイルID + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + sendBack: async ( + audioFileId: number, + options: AxiosRequestConfig = {} + ): Promise => { + // verify required parameter 'audioFileId' is not null or undefined + assertParamExists("sendBack", "audioFileId", audioFileId); + const localVarPath = `/tasks/{audioFileId}/send-back`.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; + } - if (offset !== undefined) { - localVarQueryParameter['offset'] = offset; - } + const localVarRequestOptions = { + method: "POST", + ...baseOptions, + ...options, + }; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; - if (status !== undefined) { - localVarQueryParameter['status'] = status; - } + // authentication bearer required + // http bearer authentication required + await setBearerAuthToObject(localVarHeaderParameter, configuration); - if (direction !== undefined) { - localVarQueryParameter['direction'] = direction; - } + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = + baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = { + ...localVarHeaderParameter, + ...headersFromBaseOptions, + ...options.headers, + }; - if (paramName !== undefined) { - localVarQueryParameter['paramName'] = paramName; - } + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * 指定した文字起こしタスクを一時中断します(ステータスをPendingにします) + * @summary + * @param {number} audioFileId ODMS Cloud上の音声ファイルID + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + suspend: async ( + audioFileId: number, + options: AxiosRequestConfig = {} + ): Promise => { + // verify required parameter 'audioFileId' is not null or undefined + assertParamExists("suspend", "audioFileId", audioFileId); + const localVarPath = `/tasks/{audioFileId}/suspend`.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; - - setSearchParams(localVarUrlObj, localVarQueryParameter); - let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; - localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + // authentication bearer required + // http bearer authentication required + await setBearerAuthToObject(localVarHeaderParameter, configuration); - return { - url: toPathString(localVarUrlObj), - options: localVarRequestOptions, - }; - }, - /** - * 指定した文字起こしタスクを差し戻します(ステータスをPendingにします) - * @summary - * @param {number} audioFileId ODMS Cloud上の音声ファイルID - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - sendBack: async (audioFileId: number, options: AxiosRequestConfig = {}): Promise => { - // verify required parameter 'audioFileId' is not null or undefined - assertParamExists('sendBack', 'audioFileId', audioFileId) - const localVarPath = `/tasks/{audioFileId}/send-back` - .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; - } + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = + baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = { + ...localVarHeaderParameter, + ...headersFromBaseOptions, + ...options.headers, + }; - 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) - - - - setSearchParams(localVarUrlObj, localVarQueryParameter); - let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; - localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; - - return { - url: toPathString(localVarUrlObj), - options: localVarRequestOptions, - }; - }, - /** - * 指定した文字起こしタスクを一時中断します(ステータスをPendingにします) - * @summary - * @param {number} audioFileId ODMS Cloud上の音声ファイルID - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - suspend: async (audioFileId: number, options: AxiosRequestConfig = {}): Promise => { - // verify required parameter 'audioFileId' is not null or undefined - assertParamExists('suspend', 'audioFileId', audioFileId) - const localVarPath = `/tasks/{audioFileId}/suspend` - .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) - - - - setSearchParams(localVarUrlObj, localVarQueryParameter); - let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; - localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; - - return { - url: toPathString(localVarUrlObj), - options: localVarRequestOptions, - }; - }, - } + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + }; }; /** * TasksApi - functional programming interface * @export */ -export const TasksApiFp = function(configuration?: Configuration) { - const localVarAxiosParamCreator = TasksApiAxiosParamCreator(configuration) - return { - /** - * 指定した文字起こしタスクをバックアップします(ステータスをBackupにします) - * @summary - * @param {number} audioFileId ODMS Cloud上の音声ファイルID - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - async backup(audioFileId: number, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.backup(audioFileId, options); - return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); - }, - /** - * 指定した文字起こしタスクをキャンセルします(ステータスをUploadedにします) - * @summary - * @param {number} audioFileId ODMS Cloud上の音声ファイルID - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - async cancel(audioFileId: number, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.cancel(audioFileId, options); - return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); - }, - /** - * 指定した文字起こしタスクのチェックアウト候補を変更します。 - * @summary - * @param {number} audioFileId ODMS Cloud上の音声ファイルID - * @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 - * @param {number} audioFileId ODMS Cloud上の音声ファイルID - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - async checkin(audioFileId: number, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.checkin(audioFileId, options); - return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); - }, - /** - * 指定した文字起こしタスクをチェックアウトします(ステータスをInprogressにします) - * @summary - * @param {number} audioFileId ODMS Cloud上の音声ファイルID - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - async checkout(audioFileId: number, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.checkout(audioFileId, options); - return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); - }, - /** - * 指定した文字起こしタスクの次のタスクに紐づく音声ファイルIDを取得します - * @summary - * @param {number} endedFileId 文字起こし完了したタスクの音声ファイルID - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - async getNextAudioFile(endedFileId: number, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.getNextAudioFile(endedFileId, options); - return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); - }, - /** - * 音声ファイル・文字起こしタスク情報をページ指定して取得します - * @summary - * @param {number} [limit] タスクの取得件数(指定しない場合はデフォルト値) - * @param {number} [offset] オフセット(何件目から取得するか 設定しない場合はデフォルト値) - * @param {string} [status] 取得対象とするタスクのステータス。カンマ(,)区切りで複数指定可能。設定されない場合はすべてのステータスを取得対象とする。許容するステータスの値は次の通り: Uploaded / Pending / InProgress / Finished / Backup - * @param {string} [direction] ASC/DESC - * @param {string} [paramName] JOB_NUMBER/STATUS/ENCRYPTION/AUTHOR_ID/WORK_TYPE/FILE_NAME/FILE_LENGTH/FILE_SIZE/RECORDING_STARTED_DATE/RECORDING_FINISHED_DATE/UPLOAD_DATE/TRANSCRIPTION_STARTED_DATE/TRANSCRIPTION_FINISHED_DATE - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - async getTasks(limit?: number, offset?: number, status?: string, direction?: string, paramName?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.getTasks(limit, offset, status, direction, paramName, options); - return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); - }, - /** - * 指定した文字起こしタスクを差し戻します(ステータスをPendingにします) - * @summary - * @param {number} audioFileId ODMS Cloud上の音声ファイルID - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - async sendBack(audioFileId: number, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.sendBack(audioFileId, options); - return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); - }, - /** - * 指定した文字起こしタスクを一時中断します(ステータスをPendingにします) - * @summary - * @param {number} audioFileId ODMS Cloud上の音声ファイルID - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - async suspend(audioFileId: number, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.suspend(audioFileId, options); - return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); - }, - } +export const TasksApiFp = function (configuration?: Configuration) { + const localVarAxiosParamCreator = TasksApiAxiosParamCreator(configuration); + return { + /** + * 指定した文字起こしタスクをバックアップします(ステータスをBackupにします) + * @summary + * @param {number} audioFileId ODMS Cloud上の音声ファイルID + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async backup( + audioFileId: number, + options?: AxiosRequestConfig + ): Promise< + (axios?: AxiosInstance, basePath?: string) => AxiosPromise + > { + const localVarAxiosArgs = await localVarAxiosParamCreator.backup( + audioFileId, + options + ); + return createRequestFunction( + localVarAxiosArgs, + globalAxios, + BASE_PATH, + configuration + ); + }, + /** + * 指定した文字起こしタスクをキャンセルします(ステータスをUploadedにします) + * @summary + * @param {number} audioFileId ODMS Cloud上の音声ファイルID + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async cancel( + audioFileId: number, + options?: AxiosRequestConfig + ): Promise< + (axios?: AxiosInstance, basePath?: string) => AxiosPromise + > { + const localVarAxiosArgs = await localVarAxiosParamCreator.cancel( + audioFileId, + options + ); + return createRequestFunction( + localVarAxiosArgs, + globalAxios, + BASE_PATH, + configuration + ); + }, + /** + * 指定した文字起こしタスクのチェックアウト候補を変更します。 + * @summary + * @param {number} audioFileId ODMS Cloud上の音声ファイルID + * @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 + * @param {number} audioFileId ODMS Cloud上の音声ファイルID + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async checkin( + audioFileId: number, + options?: AxiosRequestConfig + ): Promise< + (axios?: AxiosInstance, basePath?: string) => AxiosPromise + > { + const localVarAxiosArgs = await localVarAxiosParamCreator.checkin( + audioFileId, + options + ); + return createRequestFunction( + localVarAxiosArgs, + globalAxios, + BASE_PATH, + configuration + ); + }, + /** + * 指定した文字起こしタスクをチェックアウトします(ステータスをInprogressにします) + * @summary + * @param {number} audioFileId ODMS Cloud上の音声ファイルID + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async checkout( + audioFileId: number, + options?: AxiosRequestConfig + ): Promise< + (axios?: AxiosInstance, basePath?: string) => AxiosPromise + > { + const localVarAxiosArgs = await localVarAxiosParamCreator.checkout( + audioFileId, + options + ); + return createRequestFunction( + localVarAxiosArgs, + globalAxios, + BASE_PATH, + configuration + ); + }, + /** + * 指定した文字起こしタスクの次のタスクに紐づく音声ファイルIDを取得します + * @summary + * @param {number} endedFileId 文字起こし完了したタスクの音声ファイルID + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async getNextAudioFile( + endedFileId: number, + options?: AxiosRequestConfig + ): Promise< + ( + axios?: AxiosInstance, + basePath?: string + ) => AxiosPromise + > { + const localVarAxiosArgs = + await localVarAxiosParamCreator.getNextAudioFile(endedFileId, options); + return createRequestFunction( + localVarAxiosArgs, + globalAxios, + BASE_PATH, + configuration + ); + }, + /** + * 音声ファイル・文字起こしタスク情報をページ指定して取得します + * @summary + * @param {number} [limit] タスクの取得件数(指定しない場合はデフォルト値) + * @param {number} [offset] オフセット(何件目から取得するか 設定しない場合はデフォルト値) + * @param {string} [status] 取得対象とするタスクのステータス。カンマ(,)区切りで複数指定可能。設定されない場合はすべてのステータスを取得対象とする。許容するステータスの値は次の通り: Uploaded / Pending / InProgress / Finished / Backup + * @param {string} [direction] ASC/DESC + * @param {string} [paramName] JOB_NUMBER/STATUS/ENCRYPTION/AUTHOR_ID/WORK_TYPE/FILE_NAME/FILE_LENGTH/FILE_SIZE/RECORDING_STARTED_DATE/RECORDING_FINISHED_DATE/UPLOAD_DATE/TRANSCRIPTION_STARTED_DATE/TRANSCRIPTION_FINISHED_DATE + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async getTasks( + limit?: number, + offset?: number, + status?: string, + direction?: string, + paramName?: string, + options?: AxiosRequestConfig + ): Promise< + (axios?: AxiosInstance, basePath?: string) => AxiosPromise + > { + const localVarAxiosArgs = await localVarAxiosParamCreator.getTasks( + limit, + offset, + status, + direction, + paramName, + options + ); + return createRequestFunction( + localVarAxiosArgs, + globalAxios, + BASE_PATH, + configuration + ); + }, + /** + * 指定した文字起こしタスクを差し戻します(ステータスをPendingにします) + * @summary + * @param {number} audioFileId ODMS Cloud上の音声ファイルID + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async sendBack( + audioFileId: number, + options?: AxiosRequestConfig + ): Promise< + (axios?: AxiosInstance, basePath?: string) => AxiosPromise + > { + const localVarAxiosArgs = await localVarAxiosParamCreator.sendBack( + audioFileId, + options + ); + return createRequestFunction( + localVarAxiosArgs, + globalAxios, + BASE_PATH, + configuration + ); + }, + /** + * 指定した文字起こしタスクを一時中断します(ステータスをPendingにします) + * @summary + * @param {number} audioFileId ODMS Cloud上の音声ファイルID + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async suspend( + audioFileId: number, + options?: AxiosRequestConfig + ): Promise< + (axios?: AxiosInstance, basePath?: string) => AxiosPromise + > { + const localVarAxiosArgs = await localVarAxiosParamCreator.suspend( + audioFileId, + options + ); + return createRequestFunction( + localVarAxiosArgs, + globalAxios, + BASE_PATH, + configuration + ); + }, + }; }; /** * TasksApi - factory interface * @export */ -export const TasksApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) { - const localVarFp = TasksApiFp(configuration) - return { - /** - * 指定した文字起こしタスクをバックアップします(ステータスをBackupにします) - * @summary - * @param {number} audioFileId ODMS Cloud上の音声ファイルID - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - backup(audioFileId: number, options?: any): AxiosPromise { - return localVarFp.backup(audioFileId, options).then((request) => request(axios, basePath)); - }, - /** - * 指定した文字起こしタスクをキャンセルします(ステータスをUploadedにします) - * @summary - * @param {number} audioFileId ODMS Cloud上の音声ファイルID - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - cancel(audioFileId: number, options?: any): AxiosPromise { - return localVarFp.cancel(audioFileId, options).then((request) => request(axios, basePath)); - }, - /** - * 指定した文字起こしタスクのチェックアウト候補を変更します。 - * @summary - * @param {number} audioFileId ODMS Cloud上の音声ファイルID - * @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 - * @param {number} audioFileId ODMS Cloud上の音声ファイルID - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - checkin(audioFileId: number, options?: any): AxiosPromise { - return localVarFp.checkin(audioFileId, options).then((request) => request(axios, basePath)); - }, - /** - * 指定した文字起こしタスクをチェックアウトします(ステータスをInprogressにします) - * @summary - * @param {number} audioFileId ODMS Cloud上の音声ファイルID - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - checkout(audioFileId: number, options?: any): AxiosPromise { - return localVarFp.checkout(audioFileId, options).then((request) => request(axios, basePath)); - }, - /** - * 指定した文字起こしタスクの次のタスクに紐づく音声ファイルIDを取得します - * @summary - * @param {number} endedFileId 文字起こし完了したタスクの音声ファイルID - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - getNextAudioFile(endedFileId: number, options?: any): AxiosPromise { - return localVarFp.getNextAudioFile(endedFileId, options).then((request) => request(axios, basePath)); - }, - /** - * 音声ファイル・文字起こしタスク情報をページ指定して取得します - * @summary - * @param {number} [limit] タスクの取得件数(指定しない場合はデフォルト値) - * @param {number} [offset] オフセット(何件目から取得するか 設定しない場合はデフォルト値) - * @param {string} [status] 取得対象とするタスクのステータス。カンマ(,)区切りで複数指定可能。設定されない場合はすべてのステータスを取得対象とする。許容するステータスの値は次の通り: Uploaded / Pending / InProgress / Finished / Backup - * @param {string} [direction] ASC/DESC - * @param {string} [paramName] JOB_NUMBER/STATUS/ENCRYPTION/AUTHOR_ID/WORK_TYPE/FILE_NAME/FILE_LENGTH/FILE_SIZE/RECORDING_STARTED_DATE/RECORDING_FINISHED_DATE/UPLOAD_DATE/TRANSCRIPTION_STARTED_DATE/TRANSCRIPTION_FINISHED_DATE - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - getTasks(limit?: number, offset?: number, status?: string, direction?: string, paramName?: string, options?: any): AxiosPromise { - return localVarFp.getTasks(limit, offset, status, direction, paramName, options).then((request) => request(axios, basePath)); - }, - /** - * 指定した文字起こしタスクを差し戻します(ステータスをPendingにします) - * @summary - * @param {number} audioFileId ODMS Cloud上の音声ファイルID - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - sendBack(audioFileId: number, options?: any): AxiosPromise { - return localVarFp.sendBack(audioFileId, options).then((request) => request(axios, basePath)); - }, - /** - * 指定した文字起こしタスクを一時中断します(ステータスをPendingにします) - * @summary - * @param {number} audioFileId ODMS Cloud上の音声ファイルID - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - suspend(audioFileId: number, options?: any): AxiosPromise { - return localVarFp.suspend(audioFileId, options).then((request) => request(axios, basePath)); - }, - }; +export const TasksApiFactory = function ( + configuration?: Configuration, + basePath?: string, + axios?: AxiosInstance +) { + const localVarFp = TasksApiFp(configuration); + return { + /** + * 指定した文字起こしタスクをバックアップします(ステータスをBackupにします) + * @summary + * @param {number} audioFileId ODMS Cloud上の音声ファイルID + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + backup(audioFileId: number, options?: any): AxiosPromise { + return localVarFp + .backup(audioFileId, options) + .then((request) => request(axios, basePath)); + }, + /** + * 指定した文字起こしタスクをキャンセルします(ステータスをUploadedにします) + * @summary + * @param {number} audioFileId ODMS Cloud上の音声ファイルID + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + cancel(audioFileId: number, options?: any): AxiosPromise { + return localVarFp + .cancel(audioFileId, options) + .then((request) => request(axios, basePath)); + }, + /** + * 指定した文字起こしタスクのチェックアウト候補を変更します。 + * @summary + * @param {number} audioFileId ODMS Cloud上の音声ファイルID + * @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 + * @param {number} audioFileId ODMS Cloud上の音声ファイルID + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + checkin(audioFileId: number, options?: any): AxiosPromise { + return localVarFp + .checkin(audioFileId, options) + .then((request) => request(axios, basePath)); + }, + /** + * 指定した文字起こしタスクをチェックアウトします(ステータスをInprogressにします) + * @summary + * @param {number} audioFileId ODMS Cloud上の音声ファイルID + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + checkout(audioFileId: number, options?: any): AxiosPromise { + return localVarFp + .checkout(audioFileId, options) + .then((request) => request(axios, basePath)); + }, + /** + * 指定した文字起こしタスクの次のタスクに紐づく音声ファイルIDを取得します + * @summary + * @param {number} endedFileId 文字起こし完了したタスクの音声ファイルID + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getNextAudioFile( + endedFileId: number, + options?: any + ): AxiosPromise { + return localVarFp + .getNextAudioFile(endedFileId, options) + .then((request) => request(axios, basePath)); + }, + /** + * 音声ファイル・文字起こしタスク情報をページ指定して取得します + * @summary + * @param {number} [limit] タスクの取得件数(指定しない場合はデフォルト値) + * @param {number} [offset] オフセット(何件目から取得するか 設定しない場合はデフォルト値) + * @param {string} [status] 取得対象とするタスクのステータス。カンマ(,)区切りで複数指定可能。設定されない場合はすべてのステータスを取得対象とする。許容するステータスの値は次の通り: Uploaded / Pending / InProgress / Finished / Backup + * @param {string} [direction] ASC/DESC + * @param {string} [paramName] JOB_NUMBER/STATUS/ENCRYPTION/AUTHOR_ID/WORK_TYPE/FILE_NAME/FILE_LENGTH/FILE_SIZE/RECORDING_STARTED_DATE/RECORDING_FINISHED_DATE/UPLOAD_DATE/TRANSCRIPTION_STARTED_DATE/TRANSCRIPTION_FINISHED_DATE + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getTasks( + limit?: number, + offset?: number, + status?: string, + direction?: string, + paramName?: string, + options?: any + ): AxiosPromise { + return localVarFp + .getTasks(limit, offset, status, direction, paramName, options) + .then((request) => request(axios, basePath)); + }, + /** + * 指定した文字起こしタスクを差し戻します(ステータスをPendingにします) + * @summary + * @param {number} audioFileId ODMS Cloud上の音声ファイルID + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + sendBack(audioFileId: number, options?: any): AxiosPromise { + return localVarFp + .sendBack(audioFileId, options) + .then((request) => request(axios, basePath)); + }, + /** + * 指定した文字起こしタスクを一時中断します(ステータスをPendingにします) + * @summary + * @param {number} audioFileId ODMS Cloud上の音声ファイルID + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + suspend(audioFileId: number, options?: any): AxiosPromise { + return localVarFp + .suspend(audioFileId, options) + .then((request) => request(axios, basePath)); + }, + }; }; /** @@ -3653,604 +4985,985 @@ export const TasksApiFactory = function (configuration?: Configuration, basePath * @extends {BaseAPI} */ export class TasksApi extends BaseAPI { - /** - * 指定した文字起こしタスクをバックアップします(ステータスをBackupにします) - * @summary - * @param {number} audioFileId ODMS Cloud上の音声ファイルID - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof TasksApi - */ - public backup(audioFileId: number, options?: AxiosRequestConfig) { - return TasksApiFp(this.configuration).backup(audioFileId, options).then((request) => request(this.axios, this.basePath)); - } + /** + * 指定した文字起こしタスクをバックアップします(ステータスをBackupにします) + * @summary + * @param {number} audioFileId ODMS Cloud上の音声ファイルID + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof TasksApi + */ + public backup(audioFileId: number, options?: AxiosRequestConfig) { + return TasksApiFp(this.configuration) + .backup(audioFileId, options) + .then((request) => request(this.axios, this.basePath)); + } - /** - * 指定した文字起こしタスクをキャンセルします(ステータスをUploadedにします) - * @summary - * @param {number} audioFileId ODMS Cloud上の音声ファイルID - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof TasksApi - */ - public cancel(audioFileId: number, options?: AxiosRequestConfig) { - return TasksApiFp(this.configuration).cancel(audioFileId, options).then((request) => request(this.axios, this.basePath)); - } + /** + * 指定した文字起こしタスクをキャンセルします(ステータスをUploadedにします) + * @summary + * @param {number} audioFileId ODMS Cloud上の音声ファイルID + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof TasksApi + */ + public cancel(audioFileId: number, options?: AxiosRequestConfig) { + return TasksApiFp(this.configuration) + .cancel(audioFileId, options) + .then((request) => request(this.axios, this.basePath)); + } - /** - * 指定した文字起こしタスクのチェックアウト候補を変更します。 - * @summary - * @param {number} audioFileId ODMS Cloud上の音声ファイルID - * @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)); - } + /** + * 指定した文字起こしタスクのチェックアウト候補を変更します。 + * @summary + * @param {number} audioFileId ODMS Cloud上の音声ファイルID + * @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 - * @param {number} audioFileId ODMS Cloud上の音声ファイルID - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof TasksApi - */ - public checkin(audioFileId: number, options?: AxiosRequestConfig) { - return TasksApiFp(this.configuration).checkin(audioFileId, options).then((request) => request(this.axios, this.basePath)); - } + /** + * 指定した文字起こしタスクをチェックインします(ステータスをFinishedにします) + * @summary + * @param {number} audioFileId ODMS Cloud上の音声ファイルID + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof TasksApi + */ + public checkin(audioFileId: number, options?: AxiosRequestConfig) { + return TasksApiFp(this.configuration) + .checkin(audioFileId, options) + .then((request) => request(this.axios, this.basePath)); + } - /** - * 指定した文字起こしタスクをチェックアウトします(ステータスをInprogressにします) - * @summary - * @param {number} audioFileId ODMS Cloud上の音声ファイルID - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof TasksApi - */ - public checkout(audioFileId: number, options?: AxiosRequestConfig) { - return TasksApiFp(this.configuration).checkout(audioFileId, options).then((request) => request(this.axios, this.basePath)); - } + /** + * 指定した文字起こしタスクをチェックアウトします(ステータスをInprogressにします) + * @summary + * @param {number} audioFileId ODMS Cloud上の音声ファイルID + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof TasksApi + */ + public checkout(audioFileId: number, options?: AxiosRequestConfig) { + return TasksApiFp(this.configuration) + .checkout(audioFileId, options) + .then((request) => request(this.axios, this.basePath)); + } - /** - * 指定した文字起こしタスクの次のタスクに紐づく音声ファイルIDを取得します - * @summary - * @param {number} endedFileId 文字起こし完了したタスクの音声ファイルID - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof TasksApi - */ - public getNextAudioFile(endedFileId: number, options?: AxiosRequestConfig) { - return TasksApiFp(this.configuration).getNextAudioFile(endedFileId, options).then((request) => request(this.axios, this.basePath)); - } + /** + * 指定した文字起こしタスクの次のタスクに紐づく音声ファイルIDを取得します + * @summary + * @param {number} endedFileId 文字起こし完了したタスクの音声ファイルID + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof TasksApi + */ + public getNextAudioFile(endedFileId: number, options?: AxiosRequestConfig) { + return TasksApiFp(this.configuration) + .getNextAudioFile(endedFileId, options) + .then((request) => request(this.axios, this.basePath)); + } - /** - * 音声ファイル・文字起こしタスク情報をページ指定して取得します - * @summary - * @param {number} [limit] タスクの取得件数(指定しない場合はデフォルト値) - * @param {number} [offset] オフセット(何件目から取得するか 設定しない場合はデフォルト値) - * @param {string} [status] 取得対象とするタスクのステータス。カンマ(,)区切りで複数指定可能。設定されない場合はすべてのステータスを取得対象とする。許容するステータスの値は次の通り: Uploaded / Pending / InProgress / Finished / Backup - * @param {string} [direction] ASC/DESC - * @param {string} [paramName] JOB_NUMBER/STATUS/ENCRYPTION/AUTHOR_ID/WORK_TYPE/FILE_NAME/FILE_LENGTH/FILE_SIZE/RECORDING_STARTED_DATE/RECORDING_FINISHED_DATE/UPLOAD_DATE/TRANSCRIPTION_STARTED_DATE/TRANSCRIPTION_FINISHED_DATE - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof TasksApi - */ - public getTasks(limit?: number, offset?: number, status?: string, direction?: string, paramName?: string, options?: AxiosRequestConfig) { - return TasksApiFp(this.configuration).getTasks(limit, offset, status, direction, paramName, options).then((request) => request(this.axios, this.basePath)); - } + /** + * 音声ファイル・文字起こしタスク情報をページ指定して取得します + * @summary + * @param {number} [limit] タスクの取得件数(指定しない場合はデフォルト値) + * @param {number} [offset] オフセット(何件目から取得するか 設定しない場合はデフォルト値) + * @param {string} [status] 取得対象とするタスクのステータス。カンマ(,)区切りで複数指定可能。設定されない場合はすべてのステータスを取得対象とする。許容するステータスの値は次の通り: Uploaded / Pending / InProgress / Finished / Backup + * @param {string} [direction] ASC/DESC + * @param {string} [paramName] JOB_NUMBER/STATUS/ENCRYPTION/AUTHOR_ID/WORK_TYPE/FILE_NAME/FILE_LENGTH/FILE_SIZE/RECORDING_STARTED_DATE/RECORDING_FINISHED_DATE/UPLOAD_DATE/TRANSCRIPTION_STARTED_DATE/TRANSCRIPTION_FINISHED_DATE + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof TasksApi + */ + public getTasks( + limit?: number, + offset?: number, + status?: string, + direction?: string, + paramName?: string, + options?: AxiosRequestConfig + ) { + return TasksApiFp(this.configuration) + .getTasks(limit, offset, status, direction, paramName, options) + .then((request) => request(this.axios, this.basePath)); + } - /** - * 指定した文字起こしタスクを差し戻します(ステータスをPendingにします) - * @summary - * @param {number} audioFileId ODMS Cloud上の音声ファイルID - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof TasksApi - */ - public sendBack(audioFileId: number, options?: AxiosRequestConfig) { - return TasksApiFp(this.configuration).sendBack(audioFileId, options).then((request) => request(this.axios, this.basePath)); - } + /** + * 指定した文字起こしタスクを差し戻します(ステータスをPendingにします) + * @summary + * @param {number} audioFileId ODMS Cloud上の音声ファイルID + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof TasksApi + */ + public sendBack(audioFileId: number, options?: AxiosRequestConfig) { + return TasksApiFp(this.configuration) + .sendBack(audioFileId, options) + .then((request) => request(this.axios, this.basePath)); + } - /** - * 指定した文字起こしタスクを一時中断します(ステータスをPendingにします) - * @summary - * @param {number} audioFileId ODMS Cloud上の音声ファイルID - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof TasksApi - */ - public suspend(audioFileId: number, options?: AxiosRequestConfig) { - return TasksApiFp(this.configuration).suspend(audioFileId, options).then((request) => request(this.axios, this.basePath)); - } + /** + * 指定した文字起こしタスクを一時中断します(ステータスをPendingにします) + * @summary + * @param {number} audioFileId ODMS Cloud上の音声ファイルID + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof TasksApi + */ + public suspend(audioFileId: number, options?: AxiosRequestConfig) { + return TasksApiFp(this.configuration) + .suspend(audioFileId, options) + .then((request) => request(this.axios, this.basePath)); + } } - /** * UsersApi - axios parameter creator * @export */ -export const UsersApiAxiosParamCreator = function (configuration?: Configuration) { - return { - /** - * - * @summary - * @param {ConfirmRequest} confirmRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - confirmUser: async (confirmRequest: ConfirmRequest, options: AxiosRequestConfig = {}): Promise => { - // verify required parameter 'confirmRequest' is not null or undefined - assertParamExists('confirmUser', 'confirmRequest', confirmRequest) - const localVarPath = `/users/confirm`; - // 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; - } +export const UsersApiAxiosParamCreator = function ( + configuration?: Configuration +) { + return { + /** + * ライセンスを割り当てます + * @summary + * @param {AllocateLicenseRequest} allocateLicenseRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + allocateLicense: async ( + allocateLicenseRequest: AllocateLicenseRequest, + options: AxiosRequestConfig = {} + ): Promise => { + // verify required parameter 'allocateLicenseRequest' is not null or undefined + assertParamExists( + "allocateLicense", + "allocateLicenseRequest", + allocateLicenseRequest + ); + const localVarPath = `/users/license/allocate`; + // 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; + 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'; + localVarHeaderParameter["Content-Type"] = "application/json"; - setSearchParams(localVarUrlObj, localVarQueryParameter); - let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; - localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; - localVarRequestOptions.data = serializeDataIfNeeded(confirmRequest, localVarRequestOptions, configuration) + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = + baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = { + ...localVarHeaderParameter, + ...headersFromBaseOptions, + ...options.headers, + }; + localVarRequestOptions.data = serializeDataIfNeeded( + allocateLicenseRequest, + localVarRequestOptions, + configuration + ); - return { - url: toPathString(localVarUrlObj), - options: localVarRequestOptions, - }; - }, - /** - * - * @summary - * @param {ConfirmRequest} confirmRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - confirmUserAndInitPassword: async (confirmRequest: ConfirmRequest, options: AxiosRequestConfig = {}): Promise => { - // verify required parameter 'confirmRequest' is not null or undefined - assertParamExists('confirmUserAndInitPassword', 'confirmRequest', confirmRequest) - const localVarPath = `/users/confirm/initpassword`; - // 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; - } + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * + * @summary + * @param {ConfirmRequest} confirmRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + confirmUser: async ( + confirmRequest: ConfirmRequest, + options: AxiosRequestConfig = {} + ): Promise => { + // verify required parameter 'confirmRequest' is not null or undefined + assertParamExists("confirmUser", "confirmRequest", confirmRequest); + const localVarPath = `/users/confirm`; + // 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; + const localVarRequestOptions = { + method: "POST", + ...baseOptions, + ...options, + }; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + localVarHeaderParameter["Content-Type"] = "application/json"; - - localVarHeaderParameter['Content-Type'] = 'application/json'; + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = + baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = { + ...localVarHeaderParameter, + ...headersFromBaseOptions, + ...options.headers, + }; + localVarRequestOptions.data = serializeDataIfNeeded( + confirmRequest, + localVarRequestOptions, + configuration + ); - setSearchParams(localVarUrlObj, localVarQueryParameter); - let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; - localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; - localVarRequestOptions.data = serializeDataIfNeeded(confirmRequest, localVarRequestOptions, configuration) + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * + * @summary + * @param {ConfirmRequest} confirmRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + confirmUserAndInitPassword: async ( + confirmRequest: ConfirmRequest, + options: AxiosRequestConfig = {} + ): Promise => { + // verify required parameter 'confirmRequest' is not null or undefined + assertParamExists( + "confirmUserAndInitPassword", + "confirmRequest", + confirmRequest + ); + const localVarPath = `/users/confirm/initpassword`; + // 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; + } - return { - url: toPathString(localVarUrlObj), - options: localVarRequestOptions, - }; - }, - /** - * ログインしているユーザーに関連する各種情報を取得します - * @summary - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - getRelations: async (options: AxiosRequestConfig = {}): Promise => { - const localVarPath = `/users/relations`; - // 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; - const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; - const localVarHeaderParameter = {} as any; - const localVarQueryParameter = {} as any; + localVarHeaderParameter["Content-Type"] = "application/json"; - // 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, + }; + localVarRequestOptions.data = serializeDataIfNeeded( + confirmRequest, + localVarRequestOptions, + configuration + ); + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * ログインしているユーザーに関連する各種情報を取得します + * @summary + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getRelations: async ( + options: AxiosRequestConfig = {} + ): Promise => { + const localVarPath = `/users/relations`; + // 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; + } - - setSearchParams(localVarUrlObj, localVarQueryParameter); - let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; - localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + const localVarRequestOptions = { + method: "GET", + ...baseOptions, + ...options, + }; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; - return { - url: toPathString(localVarUrlObj), - options: localVarRequestOptions, - }; - }, - /** - * ログインしているユーザーのタスクソート条件を取得します - * @summary - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - getSortCriteria: async (options: AxiosRequestConfig = {}): Promise => { - const localVarPath = `/users/sort-criteria`; - // 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; - } + // authentication bearer required + // http bearer authentication required + await setBearerAuthToObject(localVarHeaderParameter, configuration); - const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; - const localVarHeaderParameter = {} as any; - const localVarQueryParameter = {} as any; + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = + baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = { + ...localVarHeaderParameter, + ...headersFromBaseOptions, + ...options.headers, + }; - // authentication bearer required - // http bearer authentication required - await setBearerAuthToObject(localVarHeaderParameter, configuration) + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * ログインしているユーザーのタスクソート条件を取得します + * @summary + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getSortCriteria: async ( + options: AxiosRequestConfig = {} + ): Promise => { + const localVarPath = `/users/sort-criteria`; + // 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; - - setSearchParams(localVarUrlObj, localVarQueryParameter); - let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; - localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + // authentication bearer required + // http bearer authentication required + await setBearerAuthToObject(localVarHeaderParameter, configuration); - return { - url: toPathString(localVarUrlObj), - options: localVarRequestOptions, - }; - }, - /** - * - * @summary - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - getUsers: async (options: AxiosRequestConfig = {}): Promise => { - const localVarPath = `/users`; - // 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; - } + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = + baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = { + ...localVarHeaderParameter, + ...headersFromBaseOptions, + ...options.headers, + }; - const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; - const localVarHeaderParameter = {} as any; - const localVarQueryParameter = {} as any; + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * + * @summary + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getUsers: async ( + options: AxiosRequestConfig = {} + ): Promise => { + const localVarPath = `/users`; + // 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; + } - // authentication bearer required - // http bearer authentication required - await setBearerAuthToObject(localVarHeaderParameter, configuration) + 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}; + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = + baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = { + ...localVarHeaderParameter, + ...headersFromBaseOptions, + ...options.headers, + }; - return { - url: toPathString(localVarUrlObj), - options: localVarRequestOptions, - }; - }, - /** - * - * @summary - * @param {SignupRequest} signupRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - signup: async (signupRequest: SignupRequest, options: AxiosRequestConfig = {}): Promise => { - // verify required parameter 'signupRequest' is not null or undefined - assertParamExists('signup', 'signupRequest', signupRequest) - const localVarPath = `/users/signup`; - // 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; - } + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * + * @summary + * @param {SignupRequest} signupRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + signup: async ( + signupRequest: SignupRequest, + options: AxiosRequestConfig = {} + ): Promise => { + // verify required parameter 'signupRequest' is not null or undefined + assertParamExists("signup", "signupRequest", signupRequest); + const localVarPath = `/users/signup`; + // 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; + 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) + // authentication bearer required + // http bearer authentication required + await setBearerAuthToObject(localVarHeaderParameter, configuration); + localVarHeaderParameter["Content-Type"] = "application/json"; - - localVarHeaderParameter['Content-Type'] = 'application/json'; + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = + baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = { + ...localVarHeaderParameter, + ...headersFromBaseOptions, + ...options.headers, + }; + localVarRequestOptions.data = serializeDataIfNeeded( + signupRequest, + localVarRequestOptions, + configuration + ); - setSearchParams(localVarUrlObj, localVarQueryParameter); - let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; - localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; - localVarRequestOptions.data = serializeDataIfNeeded(signupRequest, localVarRequestOptions, configuration) + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * ログインしているユーザーのタスクソート条件を更新します + * @summary + * @param {PostSortCriteriaRequest} postSortCriteriaRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + updateSortCriteria: async ( + postSortCriteriaRequest: PostSortCriteriaRequest, + options: AxiosRequestConfig = {} + ): Promise => { + // verify required parameter 'postSortCriteriaRequest' is not null or undefined + assertParamExists( + "updateSortCriteria", + "postSortCriteriaRequest", + postSortCriteriaRequest + ); + const localVarPath = `/users/sort-criteria`; + // 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; + } - return { - url: toPathString(localVarUrlObj), - options: localVarRequestOptions, - }; - }, - /** - * ログインしているユーザーのタスクソート条件を更新します - * @summary - * @param {PostSortCriteriaRequest} postSortCriteriaRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - updateSortCriteria: async (postSortCriteriaRequest: PostSortCriteriaRequest, options: AxiosRequestConfig = {}): Promise => { - // verify required parameter 'postSortCriteriaRequest' is not null or undefined - assertParamExists('updateSortCriteria', 'postSortCriteriaRequest', postSortCriteriaRequest) - const localVarPath = `/users/sort-criteria`; - // 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; - 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); - // 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( + postSortCriteriaRequest, + localVarRequestOptions, + configuration + ); - - localVarHeaderParameter['Content-Type'] = 'application/json'; + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * ユーザーの情報を更新します + * @summary + * @param {PostUpdateUserRequest} postUpdateUserRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + updateUser: async ( + postUpdateUserRequest: PostUpdateUserRequest, + options: AxiosRequestConfig = {} + ): Promise => { + // verify required parameter 'postUpdateUserRequest' is not null or undefined + assertParamExists( + "updateUser", + "postUpdateUserRequest", + postUpdateUserRequest + ); + const localVarPath = `/users/update`; + // 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; + } - setSearchParams(localVarUrlObj, localVarQueryParameter); - let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; - localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; - localVarRequestOptions.data = serializeDataIfNeeded(postSortCriteriaRequest, localVarRequestOptions, configuration) + const localVarRequestOptions = { + method: "POST", + ...baseOptions, + ...options, + }; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; - return { - url: toPathString(localVarUrlObj), - options: localVarRequestOptions, - }; - }, - /** - * ユーザーの情報を更新します - * @summary - * @param {PostUpdateUserRequest} postUpdateUserRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - updateUser: async (postUpdateUserRequest: PostUpdateUserRequest, options: AxiosRequestConfig = {}): Promise => { - // verify required parameter 'postUpdateUserRequest' is not null or undefined - assertParamExists('updateUser', 'postUpdateUserRequest', postUpdateUserRequest) - const localVarPath = `/users/update`; - // 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; - } + // authentication bearer required + // http bearer authentication required + await setBearerAuthToObject(localVarHeaderParameter, configuration); - const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options}; - const localVarHeaderParameter = {} as any; - const localVarQueryParameter = {} as any; + localVarHeaderParameter["Content-Type"] = "application/json"; - // 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, + }; + localVarRequestOptions.data = serializeDataIfNeeded( + postUpdateUserRequest, + localVarRequestOptions, + 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(postUpdateUserRequest, localVarRequestOptions, configuration) - - return { - url: toPathString(localVarUrlObj), - options: localVarRequestOptions, - }; - }, - } + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + }; }; /** * UsersApi - functional programming interface * @export */ -export const UsersApiFp = function(configuration?: Configuration) { - const localVarAxiosParamCreator = UsersApiAxiosParamCreator(configuration) - return { - /** - * - * @summary - * @param {ConfirmRequest} confirmRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - async confirmUser(confirmRequest: ConfirmRequest, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.confirmUser(confirmRequest, options); - return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); - }, - /** - * - * @summary - * @param {ConfirmRequest} confirmRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - async confirmUserAndInitPassword(confirmRequest: ConfirmRequest, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.confirmUserAndInitPassword(confirmRequest, options); - return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); - }, - /** - * ログインしているユーザーに関連する各種情報を取得します - * @summary - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - async getRelations(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.getRelations(options); - return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); - }, - /** - * ログインしているユーザーのタスクソート条件を取得します - * @summary - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - async getSortCriteria(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.getSortCriteria(options); - return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); - }, - /** - * - * @summary - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - async getUsers(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.getUsers(options); - return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); - }, - /** - * - * @summary - * @param {SignupRequest} signupRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - async signup(signupRequest: SignupRequest, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.signup(signupRequest, options); - return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); - }, - /** - * ログインしているユーザーのタスクソート条件を更新します - * @summary - * @param {PostSortCriteriaRequest} postSortCriteriaRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - async updateSortCriteria(postSortCriteriaRequest: PostSortCriteriaRequest, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.updateSortCriteria(postSortCriteriaRequest, options); - return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); - }, - /** - * ユーザーの情報を更新します - * @summary - * @param {PostUpdateUserRequest} postUpdateUserRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - async updateUser(postUpdateUserRequest: PostUpdateUserRequest, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.updateUser(postUpdateUserRequest, options); - return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); - }, - } +export const UsersApiFp = function (configuration?: Configuration) { + const localVarAxiosParamCreator = UsersApiAxiosParamCreator(configuration); + return { + /** + * ライセンスを割り当てます + * @summary + * @param {AllocateLicenseRequest} allocateLicenseRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async allocateLicense( + allocateLicenseRequest: AllocateLicenseRequest, + options?: AxiosRequestConfig + ): Promise< + (axios?: AxiosInstance, basePath?: string) => AxiosPromise + > { + const localVarAxiosArgs = await localVarAxiosParamCreator.allocateLicense( + allocateLicenseRequest, + options + ); + return createRequestFunction( + localVarAxiosArgs, + globalAxios, + BASE_PATH, + configuration + ); + }, + /** + * + * @summary + * @param {ConfirmRequest} confirmRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async confirmUser( + confirmRequest: ConfirmRequest, + options?: AxiosRequestConfig + ): Promise< + (axios?: AxiosInstance, basePath?: string) => AxiosPromise + > { + const localVarAxiosArgs = await localVarAxiosParamCreator.confirmUser( + confirmRequest, + options + ); + return createRequestFunction( + localVarAxiosArgs, + globalAxios, + BASE_PATH, + configuration + ); + }, + /** + * + * @summary + * @param {ConfirmRequest} confirmRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async confirmUserAndInitPassword( + confirmRequest: ConfirmRequest, + options?: AxiosRequestConfig + ): Promise< + (axios?: AxiosInstance, basePath?: string) => AxiosPromise + > { + const localVarAxiosArgs = + await localVarAxiosParamCreator.confirmUserAndInitPassword( + confirmRequest, + options + ); + return createRequestFunction( + localVarAxiosArgs, + globalAxios, + BASE_PATH, + configuration + ); + }, + /** + * ログインしているユーザーに関連する各種情報を取得します + * @summary + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async getRelations( + options?: AxiosRequestConfig + ): Promise< + ( + axios?: AxiosInstance, + basePath?: string + ) => AxiosPromise + > { + const localVarAxiosArgs = await localVarAxiosParamCreator.getRelations( + options + ); + return createRequestFunction( + localVarAxiosArgs, + globalAxios, + BASE_PATH, + configuration + ); + }, + /** + * ログインしているユーザーのタスクソート条件を取得します + * @summary + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async getSortCriteria( + options?: AxiosRequestConfig + ): Promise< + ( + axios?: AxiosInstance, + basePath?: string + ) => AxiosPromise + > { + const localVarAxiosArgs = await localVarAxiosParamCreator.getSortCriteria( + options + ); + return createRequestFunction( + localVarAxiosArgs, + globalAxios, + BASE_PATH, + configuration + ); + }, + /** + * + * @summary + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async getUsers( + options?: AxiosRequestConfig + ): Promise< + ( + axios?: AxiosInstance, + basePath?: string + ) => AxiosPromise + > { + const localVarAxiosArgs = await localVarAxiosParamCreator.getUsers( + options + ); + return createRequestFunction( + localVarAxiosArgs, + globalAxios, + BASE_PATH, + configuration + ); + }, + /** + * + * @summary + * @param {SignupRequest} signupRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async signup( + signupRequest: SignupRequest, + options?: AxiosRequestConfig + ): Promise< + (axios?: AxiosInstance, basePath?: string) => AxiosPromise + > { + const localVarAxiosArgs = await localVarAxiosParamCreator.signup( + signupRequest, + options + ); + return createRequestFunction( + localVarAxiosArgs, + globalAxios, + BASE_PATH, + configuration + ); + }, + /** + * ログインしているユーザーのタスクソート条件を更新します + * @summary + * @param {PostSortCriteriaRequest} postSortCriteriaRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async updateSortCriteria( + postSortCriteriaRequest: PostSortCriteriaRequest, + options?: AxiosRequestConfig + ): Promise< + (axios?: AxiosInstance, basePath?: string) => AxiosPromise + > { + const localVarAxiosArgs = + await localVarAxiosParamCreator.updateSortCriteria( + postSortCriteriaRequest, + options + ); + return createRequestFunction( + localVarAxiosArgs, + globalAxios, + BASE_PATH, + configuration + ); + }, + /** + * ユーザーの情報を更新します + * @summary + * @param {PostUpdateUserRequest} postUpdateUserRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async updateUser( + postUpdateUserRequest: PostUpdateUserRequest, + options?: AxiosRequestConfig + ): Promise< + (axios?: AxiosInstance, basePath?: string) => AxiosPromise + > { + const localVarAxiosArgs = await localVarAxiosParamCreator.updateUser( + postUpdateUserRequest, + options + ); + return createRequestFunction( + localVarAxiosArgs, + globalAxios, + BASE_PATH, + configuration + ); + }, + }; }; /** * UsersApi - factory interface * @export */ -export const UsersApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) { - const localVarFp = UsersApiFp(configuration) - return { - /** - * - * @summary - * @param {ConfirmRequest} confirmRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - confirmUser(confirmRequest: ConfirmRequest, options?: any): AxiosPromise { - return localVarFp.confirmUser(confirmRequest, options).then((request) => request(axios, basePath)); - }, - /** - * - * @summary - * @param {ConfirmRequest} confirmRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - confirmUserAndInitPassword(confirmRequest: ConfirmRequest, options?: any): AxiosPromise { - return localVarFp.confirmUserAndInitPassword(confirmRequest, options).then((request) => request(axios, basePath)); - }, - /** - * ログインしているユーザーに関連する各種情報を取得します - * @summary - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - getRelations(options?: any): AxiosPromise { - return localVarFp.getRelations(options).then((request) => request(axios, basePath)); - }, - /** - * ログインしているユーザーのタスクソート条件を取得します - * @summary - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - getSortCriteria(options?: any): AxiosPromise { - return localVarFp.getSortCriteria(options).then((request) => request(axios, basePath)); - }, - /** - * - * @summary - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - getUsers(options?: any): AxiosPromise { - return localVarFp.getUsers(options).then((request) => request(axios, basePath)); - }, - /** - * - * @summary - * @param {SignupRequest} signupRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - signup(signupRequest: SignupRequest, options?: any): AxiosPromise { - return localVarFp.signup(signupRequest, options).then((request) => request(axios, basePath)); - }, - /** - * ログインしているユーザーのタスクソート条件を更新します - * @summary - * @param {PostSortCriteriaRequest} postSortCriteriaRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - updateSortCriteria(postSortCriteriaRequest: PostSortCriteriaRequest, options?: any): AxiosPromise { - return localVarFp.updateSortCriteria(postSortCriteriaRequest, options).then((request) => request(axios, basePath)); - }, - /** - * ユーザーの情報を更新します - * @summary - * @param {PostUpdateUserRequest} postUpdateUserRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - */ - updateUser(postUpdateUserRequest: PostUpdateUserRequest, options?: any): AxiosPromise { - return localVarFp.updateUser(postUpdateUserRequest, options).then((request) => request(axios, basePath)); - }, - }; +export const UsersApiFactory = function ( + configuration?: Configuration, + basePath?: string, + axios?: AxiosInstance +) { + const localVarFp = UsersApiFp(configuration); + return { + /** + * ライセンスを割り当てます + * @summary + * @param {AllocateLicenseRequest} allocateLicenseRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + allocateLicense( + allocateLicenseRequest: AllocateLicenseRequest, + options?: any + ): AxiosPromise { + return localVarFp + .allocateLicense(allocateLicenseRequest, options) + .then((request) => request(axios, basePath)); + }, + /** + * + * @summary + * @param {ConfirmRequest} confirmRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + confirmUser( + confirmRequest: ConfirmRequest, + options?: any + ): AxiosPromise { + return localVarFp + .confirmUser(confirmRequest, options) + .then((request) => request(axios, basePath)); + }, + /** + * + * @summary + * @param {ConfirmRequest} confirmRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + confirmUserAndInitPassword( + confirmRequest: ConfirmRequest, + options?: any + ): AxiosPromise { + return localVarFp + .confirmUserAndInitPassword(confirmRequest, options) + .then((request) => request(axios, basePath)); + }, + /** + * ログインしているユーザーに関連する各種情報を取得します + * @summary + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getRelations(options?: any): AxiosPromise { + return localVarFp + .getRelations(options) + .then((request) => request(axios, basePath)); + }, + /** + * ログインしているユーザーのタスクソート条件を取得します + * @summary + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getSortCriteria(options?: any): AxiosPromise { + return localVarFp + .getSortCriteria(options) + .then((request) => request(axios, basePath)); + }, + /** + * + * @summary + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getUsers(options?: any): AxiosPromise { + return localVarFp + .getUsers(options) + .then((request) => request(axios, basePath)); + }, + /** + * + * @summary + * @param {SignupRequest} signupRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + signup(signupRequest: SignupRequest, options?: any): AxiosPromise { + return localVarFp + .signup(signupRequest, options) + .then((request) => request(axios, basePath)); + }, + /** + * ログインしているユーザーのタスクソート条件を更新します + * @summary + * @param {PostSortCriteriaRequest} postSortCriteriaRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + updateSortCriteria( + postSortCriteriaRequest: PostSortCriteriaRequest, + options?: any + ): AxiosPromise { + return localVarFp + .updateSortCriteria(postSortCriteriaRequest, options) + .then((request) => request(axios, basePath)); + }, + /** + * ユーザーの情報を更新します + * @summary + * @param {PostUpdateUserRequest} postUpdateUserRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + updateUser( + postUpdateUserRequest: PostUpdateUserRequest, + options?: any + ): AxiosPromise { + return localVarFp + .updateUser(postUpdateUserRequest, options) + .then((request) => request(axios, basePath)); + }, + }; }; /** @@ -4260,98 +5973,141 @@ export const UsersApiFactory = function (configuration?: Configuration, basePath * @extends {BaseAPI} */ export class UsersApi extends BaseAPI { - /** - * - * @summary - * @param {ConfirmRequest} confirmRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof UsersApi - */ - public confirmUser(confirmRequest: ConfirmRequest, options?: AxiosRequestConfig) { - return UsersApiFp(this.configuration).confirmUser(confirmRequest, options).then((request) => request(this.axios, this.basePath)); - } + /** + * ライセンスを割り当てます + * @summary + * @param {AllocateLicenseRequest} allocateLicenseRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof UsersApi + */ + public allocateLicense( + allocateLicenseRequest: AllocateLicenseRequest, + options?: AxiosRequestConfig + ) { + return UsersApiFp(this.configuration) + .allocateLicense(allocateLicenseRequest, options) + .then((request) => request(this.axios, this.basePath)); + } - /** - * - * @summary - * @param {ConfirmRequest} confirmRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof UsersApi - */ - public confirmUserAndInitPassword(confirmRequest: ConfirmRequest, options?: AxiosRequestConfig) { - return UsersApiFp(this.configuration).confirmUserAndInitPassword(confirmRequest, options).then((request) => request(this.axios, this.basePath)); - } + /** + * + * @summary + * @param {ConfirmRequest} confirmRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof UsersApi + */ + public confirmUser( + confirmRequest: ConfirmRequest, + options?: AxiosRequestConfig + ) { + return UsersApiFp(this.configuration) + .confirmUser(confirmRequest, options) + .then((request) => request(this.axios, this.basePath)); + } - /** - * ログインしているユーザーに関連する各種情報を取得します - * @summary - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof UsersApi - */ - public getRelations(options?: AxiosRequestConfig) { - return UsersApiFp(this.configuration).getRelations(options).then((request) => request(this.axios, this.basePath)); - } + /** + * + * @summary + * @param {ConfirmRequest} confirmRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof UsersApi + */ + public confirmUserAndInitPassword( + confirmRequest: ConfirmRequest, + options?: AxiosRequestConfig + ) { + return UsersApiFp(this.configuration) + .confirmUserAndInitPassword(confirmRequest, options) + .then((request) => request(this.axios, this.basePath)); + } - /** - * ログインしているユーザーのタスクソート条件を取得します - * @summary - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof UsersApi - */ - public getSortCriteria(options?: AxiosRequestConfig) { - return UsersApiFp(this.configuration).getSortCriteria(options).then((request) => request(this.axios, this.basePath)); - } + /** + * ログインしているユーザーに関連する各種情報を取得します + * @summary + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof UsersApi + */ + public getRelations(options?: AxiosRequestConfig) { + return UsersApiFp(this.configuration) + .getRelations(options) + .then((request) => request(this.axios, this.basePath)); + } - /** - * - * @summary - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof UsersApi - */ - public getUsers(options?: AxiosRequestConfig) { - return UsersApiFp(this.configuration).getUsers(options).then((request) => request(this.axios, this.basePath)); - } + /** + * ログインしているユーザーのタスクソート条件を取得します + * @summary + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof UsersApi + */ + public getSortCriteria(options?: AxiosRequestConfig) { + return UsersApiFp(this.configuration) + .getSortCriteria(options) + .then((request) => request(this.axios, this.basePath)); + } - /** - * - * @summary - * @param {SignupRequest} signupRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof UsersApi - */ - public signup(signupRequest: SignupRequest, options?: AxiosRequestConfig) { - return UsersApiFp(this.configuration).signup(signupRequest, options).then((request) => request(this.axios, this.basePath)); - } + /** + * + * @summary + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof UsersApi + */ + public getUsers(options?: AxiosRequestConfig) { + return UsersApiFp(this.configuration) + .getUsers(options) + .then((request) => request(this.axios, this.basePath)); + } - /** - * ログインしているユーザーのタスクソート条件を更新します - * @summary - * @param {PostSortCriteriaRequest} postSortCriteriaRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof UsersApi - */ - public updateSortCriteria(postSortCriteriaRequest: PostSortCriteriaRequest, options?: AxiosRequestConfig) { - return UsersApiFp(this.configuration).updateSortCriteria(postSortCriteriaRequest, options).then((request) => request(this.axios, this.basePath)); - } + /** + * + * @summary + * @param {SignupRequest} signupRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof UsersApi + */ + public signup(signupRequest: SignupRequest, options?: AxiosRequestConfig) { + return UsersApiFp(this.configuration) + .signup(signupRequest, options) + .then((request) => request(this.axios, this.basePath)); + } - /** - * ユーザーの情報を更新します - * @summary - * @param {PostUpdateUserRequest} postUpdateUserRequest - * @param {*} [options] Override http request option. - * @throws {RequiredError} - * @memberof UsersApi - */ - public updateUser(postUpdateUserRequest: PostUpdateUserRequest, options?: AxiosRequestConfig) { - return UsersApiFp(this.configuration).updateUser(postUpdateUserRequest, options).then((request) => request(this.axios, this.basePath)); - } + /** + * ログインしているユーザーのタスクソート条件を更新します + * @summary + * @param {PostSortCriteriaRequest} postSortCriteriaRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof UsersApi + */ + public updateSortCriteria( + postSortCriteriaRequest: PostSortCriteriaRequest, + options?: AxiosRequestConfig + ) { + return UsersApiFp(this.configuration) + .updateSortCriteria(postSortCriteriaRequest, options) + .then((request) => request(this.axios, this.basePath)); + } + + /** + * ユーザーの情報を更新します + * @summary + * @param {PostUpdateUserRequest} postUpdateUserRequest + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof UsersApi + */ + public updateUser( + postUpdateUserRequest: PostUpdateUserRequest, + options?: AxiosRequestConfig + ) { + return UsersApiFp(this.configuration) + .updateUser(postUpdateUserRequest, options) + .then((request) => request(this.axios, this.basePath)); + } } - - diff --git a/dictation_client/src/app/store.ts b/dictation_client/src/app/store.ts index 3299991..722801d 100644 --- a/dictation_client/src/app/store.ts +++ b/dictation_client/src/app/store.ts @@ -13,6 +13,7 @@ import partnerLicense from "features/license/partnerLicense/partnerLicenseSlice" import dictation from "features/dictation/dictationSlice"; import partner from "features/partner/partnerSlice"; import licenseOrderHistory from "features/license/licenseOrderHistory/licenseOrderHistorySlice"; +import typistGroup from "features/workflow/typistGroup/typistGroupSlice"; export const store = configureStore({ reducer: { @@ -30,6 +31,7 @@ export const store = configureStore({ partnerLicense, dictation, partner, + typistGroup, }, }); diff --git a/dictation_client/src/assets/images/group_add.svg b/dictation_client/src/assets/images/group_add.svg new file mode 100644 index 0000000..5b33700 --- /dev/null +++ b/dictation_client/src/assets/images/group_add.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + diff --git a/dictation_client/src/common/convertLocalToUTCDate.ts b/dictation_client/src/common/convertLocalToUTCDate.ts new file mode 100644 index 0000000..337c8af --- /dev/null +++ b/dictation_client/src/common/convertLocalToUTCDate.ts @@ -0,0 +1,10 @@ +// タイムゾーンを考慮し、ローカルからUTCとなるよう日付を変換する関数 +export const convertLocalToUTCDate = (date: Date) => { + const MILLISECONDS_IN_A_MINUTE = 60 * 1000; + + const timezoneOffsetMinutes = date.getTimezoneOffset(); + const timezoneOffsetMilliseconds = + timezoneOffsetMinutes * MILLISECONDS_IN_A_MINUTE; + + return new Date(date.getTime() + timezoneOffsetMilliseconds); +}; diff --git a/dictation_client/src/common/errors/code.ts b/dictation_client/src/common/errors/code.ts index 9d3f7d3..d2de6df 100644 --- a/dictation_client/src/common/errors/code.ts +++ b/dictation_client/src/common/errors/code.ts @@ -42,4 +42,8 @@ export const errorCodes = [ "E010701", // Blobファイル不在エラー "E010801", // ライセンス不在エラー "E010802", // ライセンス取り込み済みエラー + "E010803", // ライセンス発行済みエラー + "E010804", // ライセンス数不足エラー + "E010805", // ライセンス有効期限切れエラー + "E010806", // ライセンス割り当て不可エラー ] as const; diff --git a/dictation_client/src/components/header/constants.ts b/dictation_client/src/components/header/constants.ts index f3788f1..96cac3e 100644 --- a/dictation_client/src/components/header/constants.ts +++ b/dictation_client/src/components/header/constants.ts @@ -26,7 +26,9 @@ export const HEADER_NAME = "ODMS Cloud"; export const ADMIN_ONLY_TABS = [ HEADER_MENUS_LICENSE, HEADER_MENUS_USER, + HEADER_MENUS_WORKFLOW, HEADER_MENUS_PARTNER, + HEADER_MENUS_WORKFLOW, ]; /** diff --git a/dictation_client/src/components/header/index.tsx b/dictation_client/src/components/header/index.tsx index 0cd0085..eb13b31 100644 --- a/dictation_client/src/components/header/index.tsx +++ b/dictation_client/src/components/header/index.tsx @@ -11,7 +11,15 @@ interface HeaderProps { const Header: React.FC = (props) => { const { userName } = props; const location = useLocation(); - return getHeader(location.pathname, userName); + + const splitPaths = location.pathname.split("/"); + + let path = location.pathname; + if (splitPaths.length >= 2) { + path = `/${splitPaths[1]}`; + } + + return getHeader(path, userName); }; export default Header; diff --git a/dictation_client/src/features/license/licenseOrderHistory/licenseOrderHistorySlice.ts b/dictation_client/src/features/license/licenseOrderHistory/licenseOrderHistorySlice.ts index d86f33c..27d5771 100644 --- a/dictation_client/src/features/license/licenseOrderHistory/licenseOrderHistorySlice.ts +++ b/dictation_client/src/features/license/licenseOrderHistory/licenseOrderHistorySlice.ts @@ -1,6 +1,6 @@ import { PayloadAction, createSlice } from "@reduxjs/toolkit"; import { LicenseOrderHistoryState } from "./state"; -import { getLicenseOrderHistoriesAsync } from "./operations"; +import { getLicenseOrderHistoriesAsync, issueLicenseAsync } from "./operations"; import { LIMIT_ORDER_HISORY_NUM } from "./constants"; const initialState: LicenseOrderHistoryState = { @@ -52,6 +52,15 @@ export const licenseOrderHistorySlice = createSlice({ builder.addCase(getLicenseOrderHistoriesAsync.rejected, (state) => { state.apps.isLoading = false; }); + builder.addCase(issueLicenseAsync.pending, (state) => { + state.apps.isLoading = true; + }); + builder.addCase(issueLicenseAsync.fulfilled, (state) => { + state.apps.isLoading = false; + }); + builder.addCase(issueLicenseAsync.rejected, (state) => { + state.apps.isLoading = false; + }); }, }); diff --git a/dictation_client/src/features/license/licenseOrderHistory/operations.ts b/dictation_client/src/features/license/licenseOrderHistory/operations.ts index 75632d5..c6dfd9f 100644 --- a/dictation_client/src/features/license/licenseOrderHistory/operations.ts +++ b/dictation_client/src/features/license/licenseOrderHistory/operations.ts @@ -74,3 +74,70 @@ export const getLicenseOrderHistoriesAsync = createAsyncThunk< return thunkApi.rejectWithValue({ error }); } }); + +export const issueLicenseAsync = createAsyncThunk< + { + /* Empty Object */ + }, + { + // パラメータ + orderedAccountId: number; + poNumber: string; + }, + { + // rejectした時の返却値の型 + rejectValue: { + error: ErrorObject; + }; + } +>("licenses/issueLicenseAsync", async (args, thunkApi) => { + const { orderedAccountId, poNumber } = args; + // apiのConfigurationを取得する + const { getState } = thunkApi; + const state = getState() as RootState; + const { configuration, accessToken } = state.auth; + const config = new Configuration(configuration); + const accountsApi = new AccountsApi(config); + + try { + await accountsApi.issueLicense( + { + orderedAccountId, + poNumber, + }, + { + headers: { authorization: `Bearer ${accessToken}` }, + } + ); + thunkApi.dispatch( + openSnackbar({ + level: "info", + message: getTranslationID("common.message.success"), + }) + ); + return {}; + } catch (e) { + // e ⇒ errorObjectに変換" + const error = createErrorObject(e); + + let errorMessage = getTranslationID("common.message.internalServerError"); + + if (error.code === "E010803") { + errorMessage = getTranslationID( + "orderHistoriesPage.message.alreadyIssueLicense" + ); + } else if (error.code === "E010804") { + errorMessage = getTranslationID( + "orderHistoriesPage.message.notEnoughOfNumberOfLicense" + ); + } + thunkApi.dispatch( + openSnackbar({ + level: "error", + message: errorMessage, + }) + ); + + return thunkApi.rejectWithValue({ error }); + } +}); diff --git a/dictation_client/src/features/signup/operations.ts b/dictation_client/src/features/signup/operations.ts index dce701a..67e505e 100644 --- a/dictation_client/src/features/signup/operations.ts +++ b/dictation_client/src/features/signup/operations.ts @@ -3,7 +3,11 @@ import type { RootState } from "app/store"; import { ErrorObject, createErrorObject } from "common/errors"; import { getTranslationID } from "translation"; import { closeSnackbar, openSnackbar } from "features/ui/uiSlice"; -import { AccountsApi, CreateAccountRequest } from "../../api/api"; +import { + AccountsApi, + CreateAccountRequest, + GetDealersResponse, +} from "../../api/api"; import { Configuration } from "../../api/configuration"; export const signupAsync = createAsyncThunk< @@ -56,3 +60,36 @@ export const signupAsync = createAsyncThunk< return thunkApi.rejectWithValue({ error }); } }); + +export const getDealersAsync = createAsyncThunk< + GetDealersResponse, + void, + { + // rejectした時の返却値の型 + rejectValue: { + error: ErrorObject; + }; + } +>("login/getDealersAsync", async (args, thunkApi) => { + // apiのConfigurationを取得する + const { getState } = thunkApi; + const state = getState() as RootState; + const { configuration } = state.auth; + const config = new Configuration(configuration); + const accountApi = new AccountsApi(config); + + try { + const res = await accountApi.getDealers(); + return res.data; + } catch (e) { + const error = createErrorObject(e); + thunkApi.dispatch( + openSnackbar({ + level: "error", + message: getTranslationID("common.message.internalServerError"), + }) + ); + + return thunkApi.rejectWithValue({ error }); + } +}); diff --git a/dictation_client/src/features/signup/selectors.ts b/dictation_client/src/features/signup/selectors.ts index a6625d3..87c3118 100644 --- a/dictation_client/src/features/signup/selectors.ts +++ b/dictation_client/src/features/signup/selectors.ts @@ -1,3 +1,4 @@ +import { Dealer } from "api/api"; import { RootState } from "app/store"; export const selectInputValidationErrors = (state: RootState) => { @@ -56,3 +57,18 @@ export const selectPassword = (state: RootState) => state.signup.apps.password; export const selectPageState = (state: RootState) => state.signup.apps.pageState; + +export const selectAllDealers = (state: RootState) => + state.signup.domain.dealers; + +export const selectSameCountryDealers = (state: RootState) => { + const { dealers } = state.signup.domain; + const { country } = state.signup.apps; + return dealers.filter((x: Dealer) => x.country === country); +}; + +export const selectSelectedDealer = (state: RootState) => { + const { dealers } = state.signup.domain; + const { dealer } = state.signup.apps; + return dealers.find((x: Dealer) => x.id === dealer); +}; diff --git a/dictation_client/src/features/signup/signupSlice.ts b/dictation_client/src/features/signup/signupSlice.ts index d75f385..5b03e63 100644 --- a/dictation_client/src/features/signup/signupSlice.ts +++ b/dictation_client/src/features/signup/signupSlice.ts @@ -1,16 +1,20 @@ import { createSlice, PayloadAction } from "@reduxjs/toolkit"; import { SignupState } from "./state"; -import { signupAsync } from "./operations"; +import { getDealersAsync, signupAsync } from "./operations"; const initialState: SignupState = { apps: { pageState: "input", company: "", country: "", - dealer: "", + dealer: undefined, adminName: "", email: "", password: "", + dealers: [], + }, + domain: { + dealers: [], }, }; @@ -32,10 +36,11 @@ export const signupSlice = createSlice({ changeCountry: (state, action: PayloadAction<{ country: string }>) => { const { country } = action.payload; state.apps.country = country; + state.apps.dealer = undefined; }, - changeDealer: (state, action: PayloadAction<{ dealer: string }>) => { + changeDealer: (state, action: PayloadAction<{ dealer: number }>) => { const { dealer } = action.payload; - state.apps.dealer = dealer; + state.apps.dealer = Number.isNaN(dealer) ? undefined : dealer; }, changeAdminName: (state, action: PayloadAction<{ adminName: string }>) => { const { adminName } = action.payload; @@ -60,6 +65,15 @@ export const signupSlice = createSlice({ builder.addCase(signupAsync.rejected, () => { // }); + builder.addCase(getDealersAsync.pending, () => { + // + }); + builder.addCase(getDealersAsync.fulfilled, (state, action) => { + state.domain.dealers = action.payload.dealers; + }); + builder.addCase(getDealersAsync.rejected, () => { + // + }); }, }); export const { diff --git a/dictation_client/src/features/signup/state.ts b/dictation_client/src/features/signup/state.ts index 9d85fdd..164ab04 100644 --- a/dictation_client/src/features/signup/state.ts +++ b/dictation_client/src/features/signup/state.ts @@ -1,13 +1,21 @@ +import { Dealer } from "api/api"; + export interface SignupState { apps: Apps; + domain: Domain; } export interface Apps { pageState: "input" | "confirm" | "complete"; company: string; country: string; - dealer: string; + dealer?: number | undefined; adminName: string; email: string; password: string; + dealers: Dealer[]; +} + +export interface Domain { + dealers: Dealer[]; } diff --git a/dictation_client/src/features/user/constants.ts b/dictation_client/src/features/user/constants.ts index c1da1a9..27bb5dd 100644 --- a/dictation_client/src/features/user/constants.ts +++ b/dictation_client/src/features/user/constants.ts @@ -5,3 +5,9 @@ export const LICENSE_STATUS = { ALERT: "Alert", RENEW: "Renew", } as const; + +// Licenseの割り当て状態 +export const LICENSE_ALLOCATE_STATUS = { + ALLOCATED: "Allocated", + NOTALLOCATED: "Not Allocated", +} as const; diff --git a/dictation_client/src/features/user/operations.ts b/dictation_client/src/features/user/operations.ts index 8c35726..1cd1819 100644 --- a/dictation_client/src/features/user/operations.ts +++ b/dictation_client/src/features/user/operations.ts @@ -3,7 +3,12 @@ import type { RootState } from "app/store"; import { USER_ROLES } from "components/auth/constants"; import { openSnackbar } from "features/ui/uiSlice"; import { getTranslationID } from "translation"; -import { GetUsersResponse, UsersApi } from "../../api/api"; +import { + GetUsersResponse, + UsersApi, + LicensesApi, + GetAllocatableLicensesResponse, +} from "../../api/api"; import { Configuration } from "../../api/configuration"; import { ErrorObject, createErrorObject } from "../../common/errors"; @@ -59,16 +64,17 @@ export const addUserAsync = createAsyncThunk< const config = new Configuration(configuration); const usersApi = new UsersApi(config); const { addUser } = state.user.apps; + const newUser = { ...addUser }; // roleがAUTHOR以外の場合、不要なプロパティをundefinedにする - if (addUser.role !== USER_ROLES.AUTHOR) { - addUser.authorId = undefined; - addUser.encryption = undefined; - addUser.prompt = undefined; - addUser.encryptionPassword = undefined; + if (newUser.role !== USER_ROLES.AUTHOR) { + newUser.authorId = undefined; + newUser.encryption = undefined; + newUser.prompt = undefined; + newUser.encryptionPassword = undefined; } try { - await usersApi.signup(addUser, { + await usersApi.signup(newUser, { headers: { authorization: `Bearer ${accessToken}` }, }); thunkApi.dispatch( @@ -188,3 +194,115 @@ export const updateUserAsync = createAsyncThunk< return thunkApi.rejectWithValue({ error }); } }); + +export const getAllocatableLicensesAsync = createAsyncThunk< + // 正常時の戻り値の型 + GetAllocatableLicensesResponse, + // 引数 + void, + { + // rejectした時の返却値の型 + rejectValue: { + error: ErrorObject; + }; + } +>("users/getAllocatableLicensesAsync", async (args, thunkApi) => { + // apiのConfigurationを取得する + const { getState } = thunkApi; + const state = getState() as RootState; + const { configuration, accessToken } = state.auth; + const config = new Configuration(configuration); + const licensesApi = new LicensesApi(config); + + try { + const res = await licensesApi.getAllocatableLicenses({ + headers: { authorization: `Bearer ${accessToken}` }, + }); + + return res.data; + } catch (e) { + // e ⇒ errorObjectに変換 + const error = createErrorObject(e); + + const errorMessage = getTranslationID("common.message.internalServerError"); + + thunkApi.dispatch( + openSnackbar({ + level: "error", + message: errorMessage, + }) + ); + + return thunkApi.rejectWithValue({ error }); + } +}); + +export const allocateLicenseAsync = createAsyncThunk< + // 正常時の戻り値の型 + { + /* Empty Object */ + }, + // 引数 + { + userId: number; + newLicenseId: number; + }, + { + // rejectした時の返却値の型 + rejectValue: { + error: ErrorObject; + }; + } +>("users/allocateLicenseAsync", async (args, thunkApi) => { + const { userId, newLicenseId } = args; + + // apiのConfigurationを取得する + const { getState } = thunkApi; + const state = getState() as RootState; + const { configuration, accessToken } = state.auth; + const config = new Configuration(configuration); + const usersApi = new UsersApi(config); + + try { + await usersApi.allocateLicense( + { + userId, + newLicenseId, + }, + { + headers: { authorization: `Bearer ${accessToken}` }, + } + ); + thunkApi.dispatch( + openSnackbar({ + level: "info", + message: getTranslationID("common.message.success"), + }) + ); + return {}; + } catch (e) { + // e ⇒ errorObjectに変換 + const error = createErrorObject(e); + + let errorMessage = getTranslationID("common.message.internalServerError"); + + if (error.code === "E010805") { + errorMessage = getTranslationID( + "allocateLicensePopupPage.message.licenseAllocationFailure" + ); + } else if (error.code === "E010806") { + errorMessage = getTranslationID( + "allocateLicensePopupPage.message.licenseAllocationFailure" + ); + } + + thunkApi.dispatch( + openSnackbar({ + level: "error", + message: errorMessage, + }) + ); + + return thunkApi.rejectWithValue({ error }); + } +}); diff --git a/dictation_client/src/features/user/selectors.ts b/dictation_client/src/features/user/selectors.ts index 854e02b..0fd057d 100644 --- a/dictation_client/src/features/user/selectors.ts +++ b/dictation_client/src/features/user/selectors.ts @@ -1,5 +1,6 @@ import { RootState } from "app/store"; import { USER_ROLES } from "components/auth/constants"; +import { convertLocalToUTCDate } from "common/convertLocalToUTCDate"; import { AddUser, RoleType, @@ -7,7 +8,7 @@ import { isLicenseStatusType, isRoleType, } from "./types"; -import { LICENSE_STATUS } from "./constants"; +import { LICENSE_STATUS, LICENSE_ALLOCATE_STATUS } from "./constants"; export const selectInputValidationErrors = (state: RootState) => { const { name, email, role, authorId, encryption, encryptionPassword } = @@ -63,11 +64,8 @@ export const selectUpdateValidationErrors = (state: RootState) => { ); if (passwordError) { - // 最初にEncryptionがfasleで、Encryptionがtrueに変更された場合、EncryptionPasswordが必須 - if (!initEncryption) { - hasErrorIncorrectEncryptionPassword = true; - // Encryptionがある状態で変更がある場合、EncryptionPasswordが空でもエラーにしない - } else if (!encryptionPassword || encryptionPassword === "") { + // 最初にEncryptionがtrueで、EncryptionPassword変更されていない場合はエラーとしない + if (initEncryption && encryptionPassword === undefined) { hasErrorIncorrectEncryptionPassword = false; } else { hasErrorIncorrectEncryptionPassword = true; @@ -227,3 +225,105 @@ export const selectUpdateUser = (state: RootState) => export const selectHasPasswordMask = (state: RootState) => state.user.apps.hasPasswordMask; + +export const selectLicenseAllocateUserId = (state: RootState) => + state.user.apps.licenseAllocateUser.id; + +export const selectLicenseAllocateUserEmail = (state: RootState) => + state.user.apps.licenseAllocateUser.email; + +export const selectLicenseAllocateUserName = (state: RootState) => + state.user.apps.licenseAllocateUser.name; + +export const selectLicenseAllocateUserAuthorId = (state: RootState) => + state.user.apps.licenseAllocateUser.authorId; + +export const selectLicenseAllocateUserStatus = (state: RootState) => + // ライセンスが割り当てられてるかどうかのステータスを返却する。NORMAL,ALERT,RENEWはすべてライセンス割り当て扱い + state.user.apps.licenseAllocateUser.licenseStatus === LICENSE_STATUS.NOLICENSE + ? LICENSE_ALLOCATE_STATUS.NOTALLOCATED + : LICENSE_ALLOCATE_STATUS.ALLOCATED; + +export const selectLicenseAllocateUserExpirationDate = (state: RootState) => { + const { licenseStatus, remaining, expiration } = + state.user.apps.licenseAllocateUser; + + // ライセンスが割当たっていない場合は-、割当たってる場合はremaining(expiration)の形式で返却 + if (licenseStatus === LICENSE_STATUS.NOLICENSE) { + return "-"; + } + + return `${expiration}(${remaining})`; +}; + +export const selectSelectedlicenseId = (state: RootState) => + state.user.apps.selectedlicenseId; + +export const selectAllocatableLicenses = (state: RootState) => { + const { allocatableLicenses } = state.user.domain; + + // licenseIdはそのまま返却、expiryDateは「nullならundifined」「null以外ならyyyy/mm/dd(現在との差分日数)」を返却 + const transformedLicenses = allocatableLicenses.map((license) => ({ + licenseId: license.licenseId, + expiryDate: license.expiryDate + ? calculateExpiryDate(license.expiryDate) + : undefined, + })); + + return transformedLicenses; +}; + +export const selectInputValidationErrorsForLicenseAcclocation = ( + state: RootState +) => { + // 必須項目のチェック(License Acclocation画面用) + + // License available選択チェック + // 初期値である0と、「Select a license」選択時のNaNの場合エラーとする + const hasErrorEmptyLicense = + state.user.apps.selectedlicenseId === 0 || + Number.isNaN(state.user.apps.selectedlicenseId); + + return { + hasErrorEmptyLicense, + }; +}; + +// 日付の差分を計算するサブ関数 +const calculateExpiryDate = (expiryDate: string) => { + const MILLISECONDS_IN_A_DAY = 24 * 60 * 60 * 1000; // 1日のミリ秒数 + + const currentDate = new Date(); + const expirationDate = new Date(expiryDate); + + // タイムゾーンオフセットを考慮して、ローカルタイムでの日付を取得 + const currentDateLocal = convertLocalToUTCDate(currentDate); + const expirationDateLocal = convertLocalToUTCDate(expirationDate); + + // ライセンスは時刻を考慮しないので時分秒を意識しない日付を取得する + const currentDateWithoutTime = new Date( + currentDateLocal.getFullYear(), + currentDateLocal.getMonth(), + currentDateLocal.getDate() + ); + + const expirationDateWithoutTime = new Date( + expirationDateLocal.getFullYear(), + expirationDateLocal.getMonth(), + expirationDateLocal.getDate() + ); + + // 差分日数を取得 + const timeDifference = + expirationDateWithoutTime.getTime() - currentDateWithoutTime.getTime(); + const daysDifference = Math.ceil(timeDifference / MILLISECONDS_IN_A_DAY); + + // yyyy/mm/dd形式の年月日を取得 + const expirationYear = expirationDateWithoutTime.getFullYear(); + const expirationMonth = expirationDateWithoutTime.getMonth() + 1; // getMonth() の結果は0から始まるため、1を足して実際の月に合わせる + const expirationDay = expirationDateWithoutTime.getDate(); + + const formattedExpirationDate = `${expirationYear}/${expirationMonth}/${expirationDay}`; + + return `${formattedExpirationDate} (${daysDifference})`; +}; diff --git a/dictation_client/src/features/user/state.ts b/dictation_client/src/features/user/state.ts index 503d798..f25dd94 100644 --- a/dictation_client/src/features/user/state.ts +++ b/dictation_client/src/features/user/state.ts @@ -1,5 +1,5 @@ -import { User } from "../../api/api"; -import { AddUser, UpdateUser } from "./types"; +import { User, AllocatableLicenseInfo } from "../../api/api"; +import { AddUser, UpdateUser, LicenseAllocateUser } from "./types"; export interface UsersState { domain: Domain; @@ -8,12 +8,15 @@ export interface UsersState { export interface Domain { users: User[]; + allocatableLicenses: AllocatableLicenseInfo[]; } export interface Apps { addUser: AddUser; selectedUser: UpdateUser; updateUser: UpdateUser; + licenseAllocateUser: LicenseAllocateUser; + selectedlicenseId: number; hasPasswordMask: boolean; isLoading: boolean; } diff --git a/dictation_client/src/features/user/types.ts b/dictation_client/src/features/user/types.ts index 40d03f9..7f41187 100644 --- a/dictation_client/src/features/user/types.ts +++ b/dictation_client/src/features/user/types.ts @@ -50,6 +50,16 @@ export interface UpdateUser { notification: boolean; } +export interface LicenseAllocateUser { + id: number; + name: string; + email: string; + authorId: string; + licenseStatus: LicenseStatusType | string; + expiration: string; + remaining: number | string; +} + export type RoleType = typeof USER_ROLES[keyof typeof USER_ROLES]; // 受け取った値がUSER_ROLESの型であるかどうかを判定する diff --git a/dictation_client/src/features/user/userSlice.ts b/dictation_client/src/features/user/userSlice.ts index 46066d7..003a4f4 100644 --- a/dictation_client/src/features/user/userSlice.ts +++ b/dictation_client/src/features/user/userSlice.ts @@ -1,11 +1,16 @@ import { PayloadAction, createSlice } from "@reduxjs/toolkit"; import { USER_ROLES } from "components/auth/constants"; import { UsersState } from "./state"; -import { addUserAsync, listUsersAsync, updateUserAsync } from "./operations"; -import { RoleType } from "./types"; +import { + addUserAsync, + listUsersAsync, + updateUserAsync, + getAllocatableLicensesAsync, +} from "./operations"; +import { RoleType, UserView } from "./types"; const initialState: UsersState = { - domain: { users: [] }, + domain: { users: [], allocatableLicenses: [] }, apps: { updateUser: { id: 0, @@ -45,6 +50,16 @@ const initialState: UsersState = { prompt: false, encryptionPassword: "", }, + licenseAllocateUser: { + id: 0, + name: "", + email: "", + authorId: "", + licenseStatus: "", + expiration: "", + remaining: "", + }, + selectedlicenseId: 0, hasPasswordMask: false, isLoading: false, }, @@ -90,6 +105,9 @@ export const userSlice = createSlice({ ) => { const { encryption } = action.payload; state.apps.addUser.encryption = encryption; + if (!encryption) { + state.apps.addUser.encryptionPassword = undefined; + } }, changePrompt: (state, action: PayloadAction<{ prompt: boolean }>) => { const { prompt } = action.payload; @@ -170,14 +188,16 @@ export const userSlice = createSlice({ if (initEncryption && encryption && !password) { state.apps.hasPasswordMask = true; } + if (!encryption) { + state.apps.updateUser.encryptionPassword = undefined; + } }, changeUpdateEncryptionPassword: ( state, action: PayloadAction<{ encryptionPassword: string }> ) => { const { encryptionPassword } = action.payload; - state.apps.updateUser.encryptionPassword = - encryptionPassword === "" ? undefined : encryptionPassword; + state.apps.updateUser.encryptionPassword = encryptionPassword; }, changeUpdatePrompt: (state, action: PayloadAction<{ prompt: boolean }>) => { const { prompt } = action.payload; @@ -214,6 +234,30 @@ export const userSlice = createSlice({ cleanupUpdateUser: (state) => { state.apps.updateUser = initialState.apps.updateUser; }, + changeLicenseAllocateUser: ( + state, + action: PayloadAction<{ selectedUser: UserView }> + ) => { + const { selectedUser } = action.payload; + state.apps.licenseAllocateUser.id = selectedUser.id; + state.apps.licenseAllocateUser.name = selectedUser.name; + state.apps.licenseAllocateUser.email = selectedUser.email; + state.apps.licenseAllocateUser.authorId = selectedUser.authorId; + state.apps.licenseAllocateUser.licenseStatus = selectedUser.licenseStatus; + state.apps.licenseAllocateUser.expiration = selectedUser.expiration; + state.apps.licenseAllocateUser.remaining = selectedUser.remaining; + }, + changeSelectedlicenseId: ( + state, + action: PayloadAction<{ selectedlicenseId: number }> + ) => { + const { selectedlicenseId } = action.payload; + state.apps.selectedlicenseId = selectedlicenseId; + }, + cleanupLicenseAllocateInfo: (state) => { + state.apps.licenseAllocateUser = initialState.apps.licenseAllocateUser; + state.apps.selectedlicenseId = initialState.apps.selectedlicenseId; + }, }, extraReducers: (builder) => { builder.addCase(listUsersAsync.pending, (state) => { @@ -244,6 +288,16 @@ export const userSlice = createSlice({ builder.addCase(updateUserAsync.rejected, (state) => { state.apps.isLoading = false; }); + builder.addCase(getAllocatableLicensesAsync.pending, (state) => { + state.apps.isLoading = true; + }); + builder.addCase(getAllocatableLicensesAsync.fulfilled, (state, action) => { + state.domain.allocatableLicenses = action.payload.allocatableLicenses; + state.apps.isLoading = false; + }); + builder.addCase(getAllocatableLicensesAsync.rejected, (state) => { + state.apps.isLoading = false; + }); }, }); @@ -270,6 +324,9 @@ export const { changePrompt, changeEncryptionPassword, changeHasPasswordMask, + changeLicenseAllocateUser, + changeSelectedlicenseId, + cleanupLicenseAllocateInfo, } = userSlice.actions; export default userSlice.reducer; diff --git a/dictation_client/src/features/workflow/typistGroup/index.ts b/dictation_client/src/features/workflow/typistGroup/index.ts new file mode 100644 index 0000000..6812e34 --- /dev/null +++ b/dictation_client/src/features/workflow/typistGroup/index.ts @@ -0,0 +1,4 @@ +export * from "./typistGroupSlice"; +export * from "./state"; +export * from "./selectors"; +export * from "./operations"; diff --git a/dictation_client/src/features/workflow/typistGroup/operations.ts b/dictation_client/src/features/workflow/typistGroup/operations.ts new file mode 100644 index 0000000..1bc4422 --- /dev/null +++ b/dictation_client/src/features/workflow/typistGroup/operations.ts @@ -0,0 +1,43 @@ +import { createAsyncThunk } from "@reduxjs/toolkit"; +import type { RootState } from "app/store"; +import { openSnackbar } from "features/ui/uiSlice"; +import { getTranslationID } from "translation"; +import { AccountsApi, GetTypistGroupsResponse } from "../../../api/api"; +import { Configuration } from "../../../api/configuration"; +import { ErrorObject, createErrorObject } from "../../../common/errors"; + +export const listTypistGroupsAsync = createAsyncThunk< + GetTypistGroupsResponse, + void, + { + // rejectした時の返却値の型 + rejectValue: { + error: ErrorObject; + }; + } +>("dictations/listTypistGroupsAsync", async (args, thunkApi) => { + // apiのConfigurationを取得する + const { getState } = thunkApi; + const state = getState() as RootState; + const { configuration, accessToken } = state.auth; + const config = new Configuration(configuration); + const accountsApi = new AccountsApi(config); + + try { + const typistGroup = await accountsApi.getTypistGroups({ + headers: { authorization: `Bearer ${accessToken}` }, + }); + + return typistGroup.data; + } catch (e) { + // e ⇒ errorObjectに変換" + const error = createErrorObject(e); + thunkApi.dispatch( + openSnackbar({ + level: "error", + message: getTranslationID("common.message.internalServerError"), + }) + ); + return thunkApi.rejectWithValue({ error }); + } +}); diff --git a/dictation_client/src/features/workflow/typistGroup/selectors.ts b/dictation_client/src/features/workflow/typistGroup/selectors.ts new file mode 100644 index 0000000..8b37741 --- /dev/null +++ b/dictation_client/src/features/workflow/typistGroup/selectors.ts @@ -0,0 +1,7 @@ +import { RootState } from "app/store"; + +export const selectTypistGroups = (state: RootState) => + state.typistGroup.domain.typistGroups; + +export const selectIsLoading = (state: RootState) => + state.typistGroup.apps.isLoading; diff --git a/dictation_client/src/features/workflow/typistGroup/state.ts b/dictation_client/src/features/workflow/typistGroup/state.ts new file mode 100644 index 0000000..a714e0b --- /dev/null +++ b/dictation_client/src/features/workflow/typistGroup/state.ts @@ -0,0 +1,14 @@ +import { TypistGroup } from "../../../api/api"; + +export interface TypistGroupState { + apps: Apps; + domain: Domain; +} + +export interface Apps { + isLoading: boolean; +} + +export interface Domain { + typistGroups: TypistGroup[]; +} diff --git a/dictation_client/src/features/workflow/typistGroup/typistGroupSlice.ts b/dictation_client/src/features/workflow/typistGroup/typistGroupSlice.ts new file mode 100644 index 0000000..02feb96 --- /dev/null +++ b/dictation_client/src/features/workflow/typistGroup/typistGroupSlice.ts @@ -0,0 +1,32 @@ +import { createSlice } from "@reduxjs/toolkit"; +import { TypistGroupState } from "./state"; +import { listTypistGroupsAsync } from "./operations"; + +const initialState: TypistGroupState = { + apps: { + isLoading: false, + }, + domain: { + typistGroups: [], + }, +}; + +export const typistGroupSlice = createSlice({ + name: "typistGroup", + initialState, + reducers: {}, + extraReducers: (builder) => { + builder.addCase(listTypistGroupsAsync.pending, (state) => { + state.apps.isLoading = true; + }); + builder.addCase(listTypistGroupsAsync.fulfilled, (state, action) => { + state.domain.typistGroups = action.payload.typistGroups; + state.apps.isLoading = false; + }); + builder.addCase(listTypistGroupsAsync.rejected, (state) => { + state.apps.isLoading = false; + }); + }, +}); + +export default typistGroupSlice.reducer; diff --git a/dictation_client/src/pages/LicensePage/licenseOrderHistory.tsx b/dictation_client/src/pages/LicensePage/licenseOrderHistory.tsx index 8713d6e..ce8beb8 100644 --- a/dictation_client/src/pages/LicensePage/licenseOrderHistory.tsx +++ b/dictation_client/src/pages/LicensePage/licenseOrderHistory.tsx @@ -17,6 +17,7 @@ import { selectOrderHisory, selectTotal, selectTotalPage, + issueLicenseAsync, selectOffset, savePageInfo, selectCompanyName, @@ -50,6 +51,40 @@ export const LicenseOrderHistory: React.FC = ( onReturn(); }, [isLoading, onReturn]); + // issue,issueCancel,orderCancelボタンの処理終了時の情報更新用 + const UpdateHistoriesList = () => { + dispatch( + getLicenseOrderHistoriesAsync({ + limit: LIMIT_ORDER_HISORY_NUM, + offset, + }) + ); + }; + + // issueボタンを押下時の処理 + const issueLicense = useCallback( + async (poNumber: string) => { + // ダイアログ確認 + // eslint-disable-next-line no-alert + if (window.confirm(t(getTranslationID("common.message.dialogConfirm")))) { + // 注文APIの呼び出し + if (selectedRow) { + const { meta } = await dispatch( + issueLicenseAsync({ + orderedAccountId: selectedRow.accountId, + poNumber, + }) + ); + if (meta.requestStatus === "fulfilled") { + UpdateHistoriesList(); + } + } + } + }, + // eslint-disable-next-line react-hooks/exhaustive-deps + [dispatch] + ); + // ページネーションのボタンクリック時のアクション const movePage = (targetOffset: number) => { dispatch( @@ -130,7 +165,6 @@ export const LicenseOrderHistory: React.FC = ( {t(getTranslationID("orderHistoriesPage.label.status"))} - {!isLoading && licenseOrderHistory.length !== 0 && @@ -168,63 +202,68 @@ export const LicenseOrderHistory: React.FC = ( })()} - {selectedRow === undefined && - x.status === STATUS.ISSUE_REQESTING && ( - - )} - {selectedRow !== undefined && - x.status === STATUS.ISSUE_REQESTING && ( - - )} - {selectedRow !== undefined && - x.status === STATUS.ISSUED && ( - - )} + {!selectedRow && ( + + )} + {selectedRow && ( + + )} ))} diff --git a/dictation_client/src/pages/SignupPage/signupConfirm.tsx b/dictation_client/src/pages/SignupPage/signupConfirm.tsx index 6ffacd0..d3cef97 100644 --- a/dictation_client/src/pages/SignupPage/signupConfirm.tsx +++ b/dictation_client/src/pages/SignupPage/signupConfirm.tsx @@ -13,6 +13,7 @@ import { selectAdminName, selectEmail, selectPassword, + selectSelectedDealer, } from "../../features/signup/selectors"; import { signupAsync } from "../../features/signup/operations"; @@ -25,13 +26,14 @@ const SignupConfirm: React.FC = (): JSX.Element => { const adminName = useSelector(selectAdminName); const adminMail = useSelector(selectEmail); const adminPassword = useSelector(selectPassword); + const dealer = useSelector(selectSelectedDealer); const onSubmit = useCallback(() => { dispatch( signupAsync({ companyName, country, - dealerAccountId: 0, + dealerAccountId: dealer?.id ?? undefined, adminName, adminMail, adminPassword, @@ -39,7 +41,15 @@ const SignupConfirm: React.FC = (): JSX.Element => { token: "", }) ); - }, [dispatch, companyName, country, adminName, adminMail, adminPassword]); + }, [ + dispatch, + companyName, + country, + dealer, + adminName, + adminMail, + adminPassword, + ]); return (
@@ -71,7 +81,9 @@ const SignupConfirm: React.FC = (): JSX.Element => {
{t(getTranslationID("signupConfirmPage.label.dealer"))}
-
+
+

{dealer?.name} 

+
{t(getTranslationID("signupConfirmPage.text.adminInfoTitle"))} diff --git a/dictation_client/src/pages/SignupPage/signupInput.tsx b/dictation_client/src/pages/SignupPage/signupInput.tsx index 3a0f751..fd9bef5 100644 --- a/dictation_client/src/pages/SignupPage/signupInput.tsx +++ b/dictation_client/src/pages/SignupPage/signupInput.tsx @@ -1,30 +1,38 @@ import { AppDispatch } from "app/store"; import { selectAdminName, + selectAllDealers, selectCompany, selectCountry, + selectDealer, selectEmail, selectInputValidationErrors, + selectSameCountryDealers, } from "features/signup/selectors"; import { changeAdminName, changeCompany, changeCountry, + changeDealer, changeEmail, changePageState, changePassword, } from "features/signup/signupSlice"; -import React, { useCallback, useState } from "react"; +import React, { useCallback, useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { useDispatch, useSelector } from "react-redux"; -import { useNavigate } from "react-router-dom"; +import { useLocation, useNavigate } from "react-router-dom"; import { getTranslationID } from "translation"; import styles from "styles/app.module.scss"; +import { getDealersAsync } from "features/signup/operations"; +import { LANGUAGE_LIST } from "features/top/constants"; +import { openSnackbar } from "features/ui"; import { COUNTRY_LIST } from "./constants"; const SignupInput: React.FC = (): JSX.Element => { const dispatch: AppDispatch = useDispatch(); - const [t] = useTranslation(); + const [t, i18n] = useTranslation(); + const { search } = useLocation(); const navigate = useNavigate(); const [isPasswordHide, setIsPasswordHide] = useState(true); const [isOpenPolicy, setIsOpenPolicy] = useState(false); @@ -39,6 +47,7 @@ const SignupInput: React.FC = (): JSX.Element => { hasErrorIncorrectEmail, hasErrorIncorrectPassword, } = useSelector(selectInputValidationErrors); + const onSubmit = useCallback(() => { if ( hasErrorEmptyAdminName || @@ -63,11 +72,65 @@ const SignupInput: React.FC = (): JSX.Element => { hasErrorIncorrectPassword, ]); + const allDealers = useSelector(selectAllDealers); + const dealers = useSelector(selectSameCountryDealers); + const company = useSelector(selectCompany); const country = useSelector(selectCountry); + const dealer = useSelector(selectDealer); const adminName = useSelector(selectAdminName); const email = useSelector(selectEmail); + // 入力画面の初期化時の処理 + useEffect(() => { + dispatch(getDealersAsync()); + }, [dispatch]); + + useEffect(() => { + // 外部のWebサイトからの遷移時にURLのパラメータを取得 + // 以下のようなURLで遷移してきた場合に、Dealerと言語を変更する + // https://xxx/signup?dealer=1&language=en + // dealer={account_id(第四階層のアカウントID)} でDealerを指定 + // language={language(en/de/fr/es)} で言語を指定 + const query = new URLSearchParams(search); + const paramDealer = query.get("dealer"); + const language = query.get("language"); + + // URLで言語が指定されていたら言語を変更 + if (language && LANGUAGE_LIST.map((x) => x.value).includes(language)) { + i18n.changeLanguage(language); + // 既にcookieに選択言語があれば削除 + document.cookie = "language=; max-age=0"; + // cookieの期限は1年 + document.cookie = `language=${language}; max-age=31536000`; + } + + // Dealerが取得できていない場合は何もしない + if (allDealers.length === 0) { + return; + } + + // URLでDealerが指定されていたら、そのDealerを選択(国も選択したDealerの国に変更) + const urlDealer = allDealers.find( + (x) => x.id === parseInt(paramDealer ?? "", 10) + ); + if (urlDealer) { + dispatch(changeCountry({ country: urlDealer.country })); + dispatch(changeDealer({ dealer: urlDealer.id })); + } else if (paramDealer) { + // URLでDealerが指定されていたが、存在しない場合はメッセージを表示 + dispatch( + openSnackbar({ + level: "error", + message: t( + getTranslationID("signupPage.message.dealerNotFoundError") + ), + }) + ); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [i18n, dispatch, search, allDealers]); + return (
@@ -145,9 +208,29 @@ const SignupInput: React.FC = (): JSX.Element => {
{t(getTranslationID("signupPage.label.dealer"))}
- { + dispatch( + changeDealer({ + dealer: parseInt(event.target.value, 10), + }) + ); + }} + value={dealers.find((x) => x.id === dealer)?.id ?? NaN} + > + {[ + { + id: NaN, + country: "", + name: "Select dealer", + }, + ...dealers, + ].map((x) => ( + + ))} {t(getTranslationID("signupPage.text.dealerExplanation"))} diff --git a/dictation_client/src/pages/TypistGroupSettingPage/index.tsx b/dictation_client/src/pages/TypistGroupSettingPage/index.tsx new file mode 100644 index 0000000..73f7c90 --- /dev/null +++ b/dictation_client/src/pages/TypistGroupSettingPage/index.tsx @@ -0,0 +1,118 @@ +import React, { useEffect } from "react"; +import Header from "components/header"; +import Footer from "components/footer"; +import styles from "styles/app.module.scss"; +import { UpdateTokenTimer } from "components/auth/updateTokenTimer"; +import progress_activit from "assets/images/progress_activit.svg"; +import undo from "assets/images/undo.svg"; +import group_add from "assets/images/group_add.svg"; +import { useDispatch, useSelector } from "react-redux"; +import { + selectTypistGroups, + selectIsLoading, + listTypistGroupsAsync, +} from "features/workflow/typistGroup"; +import { AppDispatch } from "app/store"; +import { useTranslation } from "react-i18next"; +import { getTranslationID } from "translation"; + +const TypistGroupSettingPage: React.FC = (): JSX.Element => { + const dispatch: AppDispatch = useDispatch(); + const [t] = useTranslation(); + + const isLoading = useSelector(selectIsLoading); + const typistGroup = useSelector(selectTypistGroups); + + useEffect(() => { + dispatch(listTypistGroupsAsync()); + }, [dispatch]); + + return ( +
+
+ +
+
+
+

+ {t(getTranslationID("workflowPage.label.title"))} +

+

{` ${t( + getTranslationID("typistGroupSetting.label.title") + )}`}

+
+ +
+
+ + + + + + + + {!isLoading && typistGroup.length === 0 ? ( +

+ {t(getTranslationID("common.message.listEmpty"))} +

+ ) : ( + typistGroup.map((group) => ( + + + + + )) + )} +
+ {t(getTranslationID("typistGroupSetting.label.groupName"))} + {/** empty th */}
{group.name} + +
+ {isLoading && ( + Loading + )} +
+
+
+
+
+
+ ); +}; + +export default TypistGroupSettingPage; diff --git a/dictation_client/src/pages/UserListPage/allocateLicensePopup.tsx b/dictation_client/src/pages/UserListPage/allocateLicensePopup.tsx new file mode 100644 index 0000000..240ee8c --- /dev/null +++ b/dictation_client/src/pages/UserListPage/allocateLicensePopup.tsx @@ -0,0 +1,281 @@ +import { AppDispatch } from "app/store"; +import React, { useCallback, useEffect, useState } from "react"; +import styles from "styles/app.module.scss"; +import { useDispatch, useSelector } from "react-redux"; +import { useTranslation } from "react-i18next"; +import { + selectLicenseAllocateUserId, + selectLicenseAllocateUserEmail, + selectLicenseAllocateUserName, + selectLicenseAllocateUserAuthorId, + selectLicenseAllocateUserStatus, + selectLicenseAllocateUserExpirationDate, + selectAllocatableLicenses, + getAllocatableLicensesAsync, + changeSelectedlicenseId, + selectSelectedlicenseId, + selectIsLoading, + listUsersAsync, + allocateLicenseAsync, + cleanupLicenseAllocateInfo, + selectInputValidationErrorsForLicenseAcclocation, + LICENSE_ALLOCATE_STATUS, +} from "features/user"; +import { getTranslationID } from "translation"; +import close from "../../assets/images/close.svg"; +import progress_activit from "../../assets/images/progress_activit.svg"; + +interface AllocateLicensePopupProps { + isOpen: boolean; + onClose: () => void; +} + +export const AllocateLicensePopup: React.FC = ( + props +) => { + const { isOpen, onClose } = props; + const dispatch: AppDispatch = useDispatch(); + const { t } = useTranslation(); + + const { hasErrorEmptyLicense } = useSelector( + selectInputValidationErrorsForLicenseAcclocation + ); + + const id = useSelector(selectLicenseAllocateUserId); + const email = useSelector(selectLicenseAllocateUserEmail); + const name = useSelector(selectLicenseAllocateUserName); + const authorId = useSelector(selectLicenseAllocateUserAuthorId); + const status = useSelector(selectLicenseAllocateUserStatus); + const expirationDate = useSelector(selectLicenseAllocateUserExpirationDate); + const allocatableLicenses = useSelector(selectAllocatableLicenses); + const selectedlicenseId = useSelector(selectSelectedlicenseId); + + const [isPushAllocateButton, setIsPushAllocateButton] = + useState(false); + + const isLoading = useSelector(selectIsLoading); + + useEffect(() => { + if (isOpen) { + // 画面起動時、有効なライセンスを取得する + dispatch(getAllocatableLicensesAsync()); + } + }, [isOpen, dispatch]); + + // ポップアップを閉じる処理 + const closePopup = useCallback(() => { + if (isLoading) { + return; + } + setIsPushAllocateButton(false); + dispatch(cleanupLicenseAllocateInfo()); + onClose(); + }, [isLoading, onClose, dispatch]); + + const onAllocateLicense = useCallback(async () => { + setIsPushAllocateButton(true); + + // 入力不正時は何もしない + if (hasErrorEmptyLicense) { + return; + } + + const { meta } = await dispatch( + allocateLicenseAsync({ userId: id, newLicenseId: selectedlicenseId }) + ); + setIsPushAllocateButton(false); + + if (meta.requestStatus === "fulfilled") { + closePopup(); + dispatch(listUsersAsync()); + } + }, [dispatch, closePopup, id, selectedlicenseId, hasErrorEmptyLicense]); + + return ( +
+
+

+ {t(getTranslationID("allocateLicensePopupPage.label.title"))} + +

+
+
+
+ {t( + getTranslationID( + "allocateLicensePopupPage.label.personalInformation" + ) + )} +
+
+ {t(getTranslationID("allocateLicensePopupPage.label.email"))} +
+
+ +
+
+ {t(getTranslationID("allocateLicensePopupPage.label.name"))} +
+
+ +
+
+ {t(getTranslationID("allocateLicensePopupPage.label.authorID"))} +
+
+ +
+
+ {t(getTranslationID("allocateLicensePopupPage.label.status"))} +
+
+ { + switch (status) { + case LICENSE_ALLOCATE_STATUS.ALLOCATED: + return t( + getTranslationID( + "allocateLicensePopupPage.label.allocated" + ) + ); + case LICENSE_ALLOCATE_STATUS.NOTALLOCATED: + return t( + getTranslationID( + "allocateLicensePopupPage.label.notAllocated" + ) + ); + default: + return status; + } + })()} + className={styles.formInput} + readOnly + /> +
+
+ {t( + getTranslationID( + "allocateLicensePopupPage.label.expirationDate" + ) + )} +
+
+ +
+
+ {t( + getTranslationID( + "allocateLicensePopupPage.label.licenseInformation" + ) + )} +
+
+ {t( + getTranslationID( + "allocateLicensePopupPage.label.licenseAvailable" + ) + )} +
+
+ + {isPushAllocateButton && hasErrorEmptyLicense && ( + + {t( + getTranslationID( + "allocateLicensePopupPage.message.inputEmptyError" + ) + )} + + )} +
+
+ + Loading +
+
+
+
+
+ ); +}; diff --git a/dictation_client/src/pages/UserListPage/index.tsx b/dictation_client/src/pages/UserListPage/index.tsx index 787f902..9a04273 100644 --- a/dictation_client/src/pages/UserListPage/index.tsx +++ b/dictation_client/src/pages/UserListPage/index.tsx @@ -12,17 +12,21 @@ import { } from "features/user"; import { useTranslation } from "react-i18next"; import { getTranslationID } from "translation"; -import { isLicenseStatusType } from "features/user/types"; +import { isLicenseStatusType, UserView } from "features/user/types"; import { LICENSE_STATUS } from "features/user/constants"; import { isApproveTier } from "features/auth/utils"; import { TIERS } from "components/auth/constants"; -import { changeUpdateUser } from "features/user/userSlice"; +import { + changeUpdateUser, + changeLicenseAllocateUser, +} from "features/user/userSlice"; import personAdd from "../../assets/images/person_add.svg"; import checkFill from "../../assets/images/check_fill.svg"; import checkOutline from "../../assets/images/check_outline.svg"; import progress_activit from "../../assets/images/progress_activit.svg"; import { UserAddPopup } from "./popup"; import { UserUpdatePopup } from "./updatePopup"; +import { AllocateLicensePopup } from "./allocateLicensePopup"; const UserListPage: React.FC = (): JSX.Element => { const dispatch: AppDispatch = useDispatch(); @@ -30,6 +34,8 @@ const UserListPage: React.FC = (): JSX.Element => { const [isPopupOpen, setIsPopupOpen] = useState(false); const [isUpdatePopupOpen, setIsUpdatePopupOpen] = useState(false); + const [isAllocateLicensePopupOpen, setIsAllocateLicensePopupOpen] = + useState(false); const onOpen = useCallback(() => { setIsPopupOpen(true); @@ -43,6 +49,14 @@ const UserListPage: React.FC = (): JSX.Element => { [setIsUpdatePopupOpen, dispatch] ); + const onAllocateLicensePopupOpen = useCallback( + (selectedUser: UserView) => { + setIsAllocateLicensePopupOpen(true); + dispatch(changeLicenseAllocateUser({ selectedUser })); + }, + [setIsAllocateLicensePopupOpen, dispatch] + ); + useEffect(() => { // ユーザ一覧取得処理を呼び出す dispatch(listUsersAsync()); @@ -59,14 +73,18 @@ const UserListPage: React.FC = (): JSX.Element => { isOpen={isUpdatePopupOpen} onClose={() => { setIsUpdatePopupOpen(false); - dispatch(listUsersAsync()); }} /> { setIsPopupOpen(false); - dispatch(listUsersAsync()); + }} + /> + { + setIsAllocateLicensePopupOpen(false); }} />
@@ -164,7 +182,12 @@ const UserListPage: React.FC = (): JSX.Element => { {isTier5 && ( <>
  • - + {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions */} + { + onAllocateLicensePopupOpen(user); + }} + > {t( getTranslationID( "userListPage.label.licenseAllocation" diff --git a/dictation_client/src/pages/UserListPage/popup.tsx b/dictation_client/src/pages/UserListPage/popup.tsx index 9e0328f..35c8f0f 100644 --- a/dictation_client/src/pages/UserListPage/popup.tsx +++ b/dictation_client/src/pages/UserListPage/popup.tsx @@ -20,6 +20,7 @@ import { changePrompt, changeEncryption, changeEncryptionPassword, + listUsersAsync, } from "features/user"; import { USER_ROLES } from "components/auth/constants"; import close from "../../assets/images/close.svg"; @@ -75,6 +76,7 @@ export const UserAddPopup: React.FC = (props) => { if (meta.requestStatus === "fulfilled") { closePopup(); + dispatch(listUsersAsync()); } }, [ hasErrorEmptyName, @@ -146,9 +148,9 @@ export const UserAddPopup: React.FC = (props) => {
  • {t(getTranslationID("userListPage.label.role"))}
    -
    {t(getTranslationID("userListPage.label.setting"))}

    -

    -

    -

    {t(getTranslationID("userListPage.label.role"))}
    -
    {t(getTranslationID("userListPage.label.setting"))}

    -

    -

    -

    +); + +export default WorkflowPage; diff --git a/dictation_client/src/styles/app.module.scss b/dictation_client/src/styles/app.module.scss index 3fd239f..995e34a 100644 --- a/dictation_client/src/styles/app.module.scss +++ b/dictation_client/src/styles/app.module.scss @@ -935,13 +935,75 @@ h3 + .brCrumb .tlIcon { .modal .formInput { padding: 0.5rem 0.8rem; } +.modal .formInput[type="file"] { + border: none; + background: inherit; +} +.modal .formInput[type="file"].isHide { + display: none; +} .modal .form label { padding: 0.5rem 0 0.2rem; } +.modal .form label.formFileButton { + padding: 0.5rem 0.8rem; + border: 1px #999999 solid; + background: #ffffff; + font-size: 16px; + line-height: 1.4; + letter-spacing: 0.01rem; + font-weight: normal; + cursor: pointer; + border-radius: 0.3rem; + position: relative; + -moz-transition: all 0.3s ease-out; + -ms-transition: all 0.3s ease-out; + -webkit-transition: all 0.3s ease-out; + transition: all 0.3s ease-out; +} +.modal .form label.formFileButton:hover { + background: #f0f0f0; +} +.modal .formFileName { + display: inline-block; + width: 350px; + padding: 0.6rem 0.8rem; + border: 1px #e6e6e6 solid; + background: #e6e6e6; + box-sizing: border-box; + font-size: 16px; + line-height: 1.4; + letter-spacing: 0; + font-weight: normal; + text-align: left; +} .modal .form .icLoading { bottom: 1.5rem; left: calc(50% - 25px); } +.modal .form .tableWrap { + max-height: 60vh; + overflow-y: scroll; + margin-bottom: 1rem; +} +.modal .form .table { + width: 95%; + margin: 0 auto; +} +.modal .form .table .tableHeader th { + position: -webkit-sticky; + position: sticky; + top: 0; + padding: 0.4rem 0.5rem; + background: #282828; +} +.modal .form .table td { + padding: 0.6rem 0.4rem; +} +.modal .form .table .formInput { + width: inherit; + padding: 0.2rem 0.5rem; +} .modal .encryptionPass { display: none; } @@ -2199,12 +2261,38 @@ tr.isSelected .menuInTable li a { .workflow .table.workflow td.txWsline { white-space: pre; } -.workflow .table.group { +.workflow .table.group, +.workflow .table.template { width: 600px; } -.workflow .table.group td:last-child { +.workflow .table.group td:last-child, +.workflow .table.template td:last-child { text-align: right; } +.workflow .table.worktype { + width: 1000px; +} +.workflow .table.worktype td:last-child { + text-align: right; +} +.workflow .table .menuLink { + min-width: 3rem; + text-align: center; +} +.workflow .menuAction.worktype { + width: 1000px; +} +.workflow .menuAction.worktype .selectMenu { + padding-top: 0.5rem; + float: right; + font-size: 0.9rem; +} +.workflow .menuAction.worktype .formInput { + width: inherit; + margin-left: 0.5rem; + padding: 0.2rem 0.8rem; + font-size: 0.9rem; +} .formList dd.formChange { display: flex; diff --git a/dictation_client/src/styles/app.module.scss.d.ts b/dictation_client/src/styles/app.module.scss.d.ts index 2f0dd3c..30434e7 100644 --- a/dictation_client/src/styles/app.module.scss.d.ts +++ b/dictation_client/src/styles/app.module.scss.d.ts @@ -60,6 +60,12 @@ declare const classNames: { readonly modalTitleIcon: "modalTitleIcon"; readonly last: "last"; readonly slideSet: "slideSet"; + readonly isHide: "isHide"; + readonly formFileButton: "formFileButton"; + readonly formFileName: "formFileName"; + readonly tableWrap: "tableWrap"; + readonly table: "table"; + readonly tableHeader: "tableHeader"; readonly encryptionPass: "encryptionPass"; readonly pageHeader: "pageHeader"; readonly pageTitle: "pageTitle"; @@ -75,8 +81,6 @@ declare const classNames: { readonly snackbarMessage: "snackbarMessage"; readonly snackbarIcon: "snackbarIcon"; readonly snackbarIconClose: "snackbarIconClose"; - readonly table: "table"; - readonly tableHeader: "tableHeader"; readonly hasSort: "hasSort"; readonly isActiveAz: "isActiveAz"; readonly isActiveZa: "isActiveZa"; @@ -100,8 +104,8 @@ declare const classNames: { readonly menuAction: "menuAction"; readonly inTable: "inTable"; readonly menuLink: "menuLink"; - readonly colorLink: "colorLink"; readonly menuIcon: "menuIcon"; + readonly colorLink: "colorLink"; readonly isDisable: "isDisable"; readonly icCheckCircle: "icCheckCircle"; readonly icInTable: "icInTable"; @@ -112,7 +116,6 @@ declare const classNames: { readonly displayOptions: "displayOptions"; readonly tableFilter: "tableFilter"; readonly tableFilter2: "tableFilter2"; - readonly tableWrap: "tableWrap"; readonly txWsline: "txWsline"; readonly hidePri: "hidePri"; readonly opPri: "opPri"; @@ -178,6 +181,9 @@ declare const classNames: { readonly changeTitle: "changeTitle"; readonly role4: "role4"; readonly group: "group"; + readonly template: "template"; + readonly worktype: "worktype"; + readonly selectMenu: "selectMenu"; readonly alignCenter: "alignCenter"; readonly alignLeft: "alignLeft"; readonly alignRight: "alignRight"; @@ -203,6 +209,5 @@ declare const classNames: { readonly txNormal: "txNormal"; readonly txIcon: "txIcon"; readonly txWswrap: "txWswrap"; - readonly widthMid: "widthMid"; }; export = classNames; diff --git a/dictation_client/src/translation/de.json b/dictation_client/src/translation/de.json index 54bb849..a8407fd 100644 --- a/dictation_client/src/translation/de.json +++ b/dictation_client/src/translation/de.json @@ -41,7 +41,8 @@ "message": { "inputEmptyError": "(de)この項目の入力は必須です。入力してください。", "passwordIncorrectError": "(de)入力されたパスワードがルールを満たしていません。下記のルールを満たすパスワードを入力してください。", - "emailIncorrectError": "(de)メールアドレスの形式が不正です。正しいメールアドレスの形式で入力してください。" + "emailIncorrectError": "(de)メールアドレスの形式が不正です。正しいメールアドレスの形式で入力してください。", + "dealerNotFoundError": "(de)指定されたディーラーが見つかりませんでした。直接ディーラーを指定してください。" }, "text": { "title": "(de)Create your account", @@ -324,6 +325,46 @@ "issueCancel": "(de)Issue Cancel", "orderCancel": "(de)Order Cancel", "histories": "(de)histories" + }, + "message": { + "notEnoughOfNumberOfLicense": "(de)ライセンスが不足しているため、発行することができませんでした。ライセンスの注文を行ってください。", + "alreadyIssueLicense": "(de)すでに発行済みの注文です。画面を更新してください。" + } + }, + "allocateLicensePopupPage": { + "label": { + "title": "(de)License Allocation", + "personalInformation": "(de)Personal Information", + "email": "(de)Email", + "name": "(de)Name", + "authorID": "(de)Author ID", + "status": "(de)Status", + "allocated": "(de)Allocated", + "notAllocated": "(de)Not Allocated", + "expirationDate": "(de)Expiration date", + "licenseInformation": "(de)License Information", + "licenseAvailable": "(de)License available", + "dropDownHeading": "(de)Select a license.", + "oneYear": "(de)One Year", + "allocateLicense": "(de)OK" + }, + "message": { + "inputEmptyError": "(de)この項目の入力は必須です。入力してください。", + "licenseAllocationFailure": "(de)ライセンスの割り当てに失敗しました。他のライセンスを選択して再度割り当てをしてください。" + } + }, + "workflowPage": { + "label": { + "title": "(de)Workflow" + } + }, + "typistGroupSetting": { + "label": { + "title": "(de)Transctiprionist Group", + "return": "(de)Return", + "addGroup": "(de)Add Group", + "groupName": "(de)Group Name", + "edit": "(de)Edit" } } -} +} \ No newline at end of file diff --git a/dictation_client/src/translation/en.json b/dictation_client/src/translation/en.json index 44ba9e9..723c04f 100644 --- a/dictation_client/src/translation/en.json +++ b/dictation_client/src/translation/en.json @@ -41,7 +41,8 @@ "message": { "inputEmptyError": "この項目の入力は必須です。入力してください。", "passwordIncorrectError": "入力されたパスワードがルールを満たしていません。下記のルールを満たすパスワードを入力してください。", - "emailIncorrectError": "メールアドレスの形式が不正です。正しいメールアドレスの形式で入力してください。" + "emailIncorrectError": "メールアドレスの形式が不正です。正しいメールアドレスの形式で入力してください。", + "dealerNotFoundError": "指定されたディーラーが見つかりませんでした。直接ディーラーを指定してください。" }, "text": { "title": "Create your account", @@ -324,6 +325,46 @@ "issueCancel": "Issue Cancel", "orderCancel": "Order Cancel", "histories": "histories" + }, + "message": { + "notEnoughOfNumberOfLicense": "ライセンスが不足しているため、発行することができませんでした。ライセンスの注文を行ってください。", + "alreadyIssueLicense": "すでに発行済みの注文です。画面を更新してください。" + } + }, + "allocateLicensePopupPage": { + "label": { + "title": "License Allocation", + "personalInformation": "Personal Information", + "email": "Email", + "name": "Name", + "authorID": "Author ID", + "status": "Status", + "allocated": "Allocated", + "notAllocated": "Not Allocated", + "expirationDate": "Expiration date", + "licenseInformation": "License Information", + "licenseAvailable": "License available", + "dropDownHeading": "Select a license.", + "oneYear": "One Year", + "allocateLicense": "OK" + }, + "message": { + "inputEmptyError": "この項目の入力は必須です。入力してください。", + "licenseAllocationFailure": "ライセンスの割り当てに失敗しました。他のライセンスを選択して再度割り当てをしてください。" + } + }, + "workflowPage": { + "label": { + "title": "Workflow" + } + }, + "typistGroupSetting": { + "label": { + "title": "Transctiprionist Group", + "return": "Return", + "addGroup": "Add Group", + "groupName": "Group Name", + "edit": "Edit" } } -} +} \ No newline at end of file diff --git a/dictation_client/src/translation/es.json b/dictation_client/src/translation/es.json index 0394154..6affad2 100644 --- a/dictation_client/src/translation/es.json +++ b/dictation_client/src/translation/es.json @@ -41,7 +41,8 @@ "message": { "inputEmptyError": "(es)この項目の入力は必須です。入力してください。", "passwordIncorrectError": "(es)入力されたパスワードがルールを満たしていません。下記のルールを満たすパスワードを入力してください。", - "emailIncorrectError": "(es)メールアドレスの形式が不正です。正しいメールアドレスの形式で入力してください。" + "emailIncorrectError": "(es)メールアドレスの形式が不正です。正しいメールアドレスの形式で入力してください。", + "dealerNotFoundError": "(es)指定されたディーラーが見つかりませんでした。直接ディーラーを指定してください。" }, "text": { "title": "(es)Create your account", @@ -324,6 +325,46 @@ "issueCancel": "(es)Issue Cancel", "orderCancel": "(es)Order Cancel", "histories": "(es)histories" + }, + "message": { + "notEnoughOfNumberOfLicense": "(es)ライセンスが不足しているため、発行することができませんでした。ライセンスの注文を行ってください。", + "alreadyIssueLicense": "(es)すでに発行済みの注文です。画面を更新してください。" + } + }, + "allocateLicensePopupPage": { + "label": { + "title": "(es)License Allocation", + "personalInformation": "(es)Personal Information", + "email": "(es)Email", + "name": "(es)Name", + "authorID": "(es)Author ID", + "status": "(es)Status", + "allocated": "(es)Allocated", + "notAllocated": "(es)Not Allocated", + "expirationDate": "(es)Expiration date", + "licenseInformation": "(es)License Information", + "licenseAvailable": "(es)License available", + "dropDownHeading": "(es)Select a license.", + "oneYear": "(es)One Year", + "allocateLicense": "(es)OK" + }, + "message": { + "inputEmptyError": "(es)この項目の入力は必須です。入力してください。", + "licenseAllocationFailure": "(es)ライセンスの割り当てに失敗しました。他のライセンスを選択して再度割り当てをしてください。" + } + }, + "workflowPage": { + "label": { + "title": "(es)Workflow" + } + }, + "typistGroupSetting": { + "label": { + "title": "(es)Transctiprionist Group", + "return": "(es)Return", + "addGroup": "(es)Add Group", + "groupName": "(es)Group Name", + "edit": "(es)Edit" } } -} +} \ No newline at end of file diff --git a/dictation_client/src/translation/fr.json b/dictation_client/src/translation/fr.json index a1d7e74..ade9c18 100644 --- a/dictation_client/src/translation/fr.json +++ b/dictation_client/src/translation/fr.json @@ -41,7 +41,8 @@ "message": { "inputEmptyError": "(fr)この項目の入力は必須です。入力してください。", "passwordIncorrectError": "(fr)入力されたパスワードがルールを満たしていません。下記のルールを満たすパスワードを入力してください。", - "emailIncorrectError": "(fr)メールアドレスの形式が不正です。正しいメールアドレスの形式で入力してください。" + "emailIncorrectError": "(fr)メールアドレスの形式が不正です。正しいメールアドレスの形式で入力してください。", + "dealerNotFoundError": "(fr)指定されたディーラーが見つかりませんでした。直接ディーラーを指定してください。" }, "text": { "title": "(fr)Create your account", @@ -324,6 +325,46 @@ "issueCancel": "(fr)Issue Cancel", "orderCancel": "(fr)Order Cancel", "histories": "(fr)histories" + }, + "message": { + "notEnoughOfNumberOfLicense": "(fr)ライセンスが不足しているため、発行することができませんでした。ライセンスの注文を行ってください。", + "alreadyIssueLicense": "(fr)すでに発行済みの注文です。画面を更新してください。" + } + }, + "allocateLicensePopupPage": { + "label": { + "title": "(fr)License Allocation", + "personalInformation": "(fr)Personal Information", + "email": "(fr)Email", + "name": "(fr)Name", + "authorID": "(fr)Author ID", + "status": "(fr)Status", + "allocated": "(fr)Allocated", + "notAllocated": "(fr)Not Allocated", + "expirationDate": "(fr)Expiration date", + "licenseInformation": "(fr)License Information", + "licenseAvailable": "(fr)License available", + "dropDownHeading": "(fr)Select a license.", + "oneYear": "(fr)One Year", + "allocateLicense": "(fr)OK" + }, + "message": { + "inputEmptyError": "(fr)この項目の入力は必須です。入力してください。", + "licenseAllocationFailure": "(fr)ライセンスの割り当てに失敗しました。他のライセンスを選択して再度割り当てをしてください。" + } + }, + "workflowPage": { + "label": { + "title": "(fr)Workflow" + } + }, + "typistGroupSetting": { + "label": { + "title": "(fr)Transctiprionist Group", + "return": "(fr)Return", + "addGroup": "(fr)Add Group", + "groupName": "(fr)Group Name", + "edit": "(fr)Edit" } } -} +} \ No newline at end of file diff --git a/dictation_server/db/migrations/028-create_lisence_allocation_history.sql b/dictation_server/db/migrations/028-create_lisence_allocation_history.sql new file mode 100644 index 0000000..4dea86c --- /dev/null +++ b/dictation_server/db/migrations/028-create_lisence_allocation_history.sql @@ -0,0 +1,16 @@ +-- +migrate Up +CREATE TABLE IF NOT EXISTS `lisence_allocation_history` ( + `user_id` BIGINT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY COMMENT 'ユーザーID', + `license_id` BIGINT UNSIGNED NOT NULL COMMENT 'ライセンスID', + `allocate_type` VARCHAR(255) NOT NULL COMMENT '割り当て種別(割当解除/割当)', + `executed_at` TIMESTAMP NOT NULL COMMENT '実施日時', + `switch_from_type` VARCHAR(255) NOT NULL COMMENT '切り替え元種別(特になし/カード/トライアル)', + `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 '更新時刻' +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci; + +-- +migrate Down +DROP TABLE `lisence_allocation_history`; \ No newline at end of file diff --git a/dictation_server/db/migrations/029-create_license_allocation_history.sql b/dictation_server/db/migrations/029-create_license_allocation_history.sql new file mode 100644 index 0000000..8d30cfc --- /dev/null +++ b/dictation_server/db/migrations/029-create_license_allocation_history.sql @@ -0,0 +1,19 @@ +-- +migrate Up +DROP TABLE IF EXISTS `lisence_allocation_history`; + +CREATE TABLE IF NOT EXISTS `license_allocation_history` ( + `id` BIGINT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY COMMENT '割り当て履歴ID', + `user_id` BIGINT UNSIGNED NOT NULL COMMENT 'ユーザーID', + `license_id` BIGINT UNSIGNED NOT NULL COMMENT 'ライセンスID', + `is_allocated` BOOLEAN NOT NULL DEFAULT 0 COMMENT '割り当て済みか', + `executed_at` TIMESTAMP NOT NULL COMMENT '実施日時', + `switch_from_type` VARCHAR(255) NOT NULL COMMENT '切り替え元種別(特になし/カード/トライアル)', + `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 '更新時刻' +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci; + +-- +migrate Down +DROP TABLE `license_allocation_history`; \ No newline at end of file diff --git a/dictation_server/src/api/odms/openapi.json b/dictation_server/src/api/odms/openapi.json index ddc9bf4..0b3195b 100644 --- a/dictation_server/src/api/odms/openapi.json +++ b/dictation_server/src/api/odms/openapi.json @@ -298,6 +298,60 @@ }, "tags": ["accounts"], "security": [{ "bearer": [] }] + }, + "post": { + "operationId": "createTypistGroup", + "summary": "", + "description": "ログインしているユーザーのアカウント配下にタイピストグループを追加します", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateTypistGroupRequest" + } + } + } + }, + "responses": { + "200": { + "description": "成功時のレスポンス", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateTypistGroupResponse" + } + } + } + }, + "400": { + "description": "グループ名が空の場合/ユーザーが存在しない場合", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/ErrorResponse" } + } + } + }, + "401": { + "description": "認証エラー", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/ErrorResponse" } + } + } + }, + "500": { + "description": "想定外のサーバーエラー", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/ErrorResponse" } + } + } + } + }, + "tags": ["accounts"], + "security": [{ "bearer": [] }] } }, "/accounts/partner": { @@ -882,6 +936,118 @@ "security": [{ "bearer": [] }] } }, + "/users/license/allocate": { + "post": { + "operationId": "allocateLicense", + "summary": "", + "description": "ライセンスを割り当てます", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AllocateLicenseRequest" + } + } + } + }, + "responses": { + "200": { + "description": "成功時のレスポンス", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AllocateLicenseResponse" + } + } + } + }, + "400": { + "description": "割り当て失敗時", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/ErrorResponse" } + } + } + }, + "401": { + "description": "認証エラー", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/ErrorResponse" } + } + } + }, + "500": { + "description": "想定外のサーバーエラー", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/ErrorResponse" } + } + } + } + }, + "tags": ["users"], + "security": [{ "bearer": [] }] + } + }, + "/users/license/deallocate": { + "post": { + "operationId": "deallocateLicense", + "summary": "", + "description": "ライセンス割り当てを解除します", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeallocateLicenseRequest" + } + } + } + }, + "responses": { + "200": { + "description": "成功時のレスポンス", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeallocateLicenseResponse" + } + } + } + }, + "400": { + "description": "すでにライセンスが割り当て解除されている時", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/ErrorResponse" } + } + } + }, + "401": { + "description": "認証エラー", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/ErrorResponse" } + } + } + }, + "500": { + "description": "想定外のサーバーエラー", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/ErrorResponse" } + } + } + } + }, + "tags": ["users"], + "security": [{ "bearer": [] }] + } + }, "/files/audio/upload-finished": { "post": { "operationId": "uploadFinished", @@ -1816,6 +1982,44 @@ "security": [{ "bearer": [] }] } }, + "/licenses/allocatable": { + "get": { + "operationId": "getAllocatableLicenses", + "summary": "", + "description": "割り当て可能なライセンスを取得します", + "parameters": [], + "responses": { + "200": { + "description": "成功時のレスポンス", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetAllocatableLicensesResponse" + } + } + } + }, + "401": { + "description": "認証エラー", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/ErrorResponse" } + } + } + }, + "500": { + "description": "想定外のサーバーエラー", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/ErrorResponse" } + } + } + } + }, + "tags": ["licenses"], + "security": [{ "bearer": [] }] + } + }, "/notification/register": { "post": { "operationId": "register", @@ -1923,7 +2127,7 @@ "minLength": 2, "maxLength": 2 }, - "dealerAccountId": { "type": "number", "nullable": true }, + "dealerAccountId": { "type": "number" }, "adminName": { "type": "string" }, "adminMail": { "type": "string" }, "adminPassword": { "type": "string" }, @@ -1936,7 +2140,6 @@ "required": [ "companyName", "country", - "dealerAccountId", "adminName", "adminMail", "adminPassword", @@ -2028,6 +2231,23 @@ }, "required": ["typistGroups"] }, + "CreateTypistGroupRequest": { + "type": "object", + "properties": { + "typistGroupName": { + "type": "string", + "minLength": 1, + "maxLength": 50 + }, + "typistIds": { + "minItems": 1, + "type": "array", + "items": { "type": "string" } + } + }, + "required": ["typistGroupName", "typistIds"] + }, + "CreateTypistGroupResponse": { "type": "object", "properties": {} }, "CreatePartnerAccountRequest": { "type": "object", "properties": { @@ -2373,6 +2593,26 @@ "required": ["id", "role", "autoRenew", "licenseAlart", "notification"] }, "PostUpdateUserResponse": { "type": "object", "properties": {} }, + "AllocateLicenseRequest": { + "type": "object", + "properties": { + "userId": { "type": "number", "description": "ユーザーID" }, + "newLicenseId": { + "type": "number", + "description": "割り当てるライセンスのID" + } + }, + "required": ["userId", "newLicenseId"] + }, + "AllocateLicenseResponse": { "type": "object", "properties": {} }, + "DeallocateLicenseRequest": { + "type": "object", + "properties": { + "userId": { "type": "number", "description": "ユーザーID" } + }, + "required": ["userId"] + }, + "DeallocateLicenseResponse": { "type": "object", "properties": {} }, "AudioOptionItem": { "type": "object", "properties": { @@ -2671,6 +2911,24 @@ "required": ["cardLicenseKey"] }, "ActivateCardLicensesResponse": { "type": "object", "properties": {} }, + "AllocatableLicenseInfo": { + "type": "object", + "properties": { + "licenseId": { "type": "number" }, + "expiryDate": { "format": "date-time", "type": "string" } + }, + "required": ["licenseId", "expiryDate"] + }, + "GetAllocatableLicensesResponse": { + "type": "object", + "properties": { + "allocatableLicenses": { + "type": "array", + "items": { "$ref": "#/components/schemas/AllocatableLicenseInfo" } + } + }, + "required": ["allocatableLicenses"] + }, "RegisterRequest": { "type": "object", "properties": { diff --git a/dictation_server/src/common/error/code.ts b/dictation_server/src/common/error/code.ts index 94fa41c..43aec9f 100644 --- a/dictation_server/src/common/error/code.ts +++ b/dictation_server/src/common/error/code.ts @@ -42,4 +42,8 @@ export const ErrorCodes = [ 'E010701', // Blobファイル不在エラー 'E010801', // ライセンス不在エラー 'E010802', // ライセンス取り込み済みエラー + 'E010803', // ライセンス発行済みエラー + 'E010804', // ライセンス不足エラー + 'E010805', // ライセンス有効期限切れエラー + 'E010806', // ライセンス割り当て不可エラー ] as const; diff --git a/dictation_server/src/common/error/message.ts b/dictation_server/src/common/error/message.ts index bbc1b40..e41ba72 100644 --- a/dictation_server/src/common/error/message.ts +++ b/dictation_server/src/common/error/message.ts @@ -31,4 +31,8 @@ export const errors: Errors = { E010701: 'File not found in Blob Storage Error.', E010801: 'License not exist Error', E010802: 'License already activated Error', + E010803: 'License already issued Error', + E010804: 'License shortage Error', + E010805: 'License is expired Error', + E010806: 'License is unavailable Error', }; diff --git a/dictation_server/src/common/log/context.ts b/dictation_server/src/common/log/context.ts index 575132d..cd6079d 100644 --- a/dictation_server/src/common/log/context.ts +++ b/dictation_server/src/common/log/context.ts @@ -1,7 +1,7 @@ import { Context } from './types'; -export const makeContext = (externaiId: string): Context => { +export const makeContext = (externalId: string): Context => { return { - trackingId: externaiId, + trackingId: externalId, }; }; diff --git a/dictation_server/src/common/test/overrides.ts b/dictation_server/src/common/test/overrides.ts new file mode 100644 index 0000000..ec2b531 --- /dev/null +++ b/dictation_server/src/common/test/overrides.ts @@ -0,0 +1,218 @@ +import { Context } from '../log'; +import { + AdB2cService, + ConflictError, +} from '../../gateways/adb2c/adb2c.service'; +import { SendGridService } from '../../gateways/sendgrid/sendgrid.service'; +import { User, newUser } from '../../repositories/users/entity/user.entity'; +import { UsersRepositoryService } from '../../repositories/users/users.repository.service'; +import { BlobstorageService } from '../../gateways/blobstorage/blobstorage.service'; +import { AccountsRepositoryService } from '../../repositories/accounts/accounts.repository.service'; +import { Account } from '../../repositories/accounts/entity/account.entity'; + +// ### ユニットテスト用コード以外では絶対に使用してはいけないダーティな手段を使用しているが、他の箇所では使用しないこと ### + +/** + * adB2cServiceのモックを作成して、TServiceが依存するサービス(adB2cService)の参照を上書きする + * ※ serviceに指定するオブジェクトは`adB2cService: AdB2cService`メンバ変数を持つ必要がある + * @param service 上書きしたいTService + * @param overrides adB2cServiceの各種メソッドのモックが返す値(省略した場合は既定のダミーの値) + */ +export const overrideAdB2cService = ( + service: TService, + overrides: { + createUser?: ( + context: Context, + email: string, + password: string, + username: string, + ) => Promise<{ sub: string } | ConflictError>; + deleteUser?: (externalId: string, context: Context) => Promise; + }, +): void => { + // テストコードでのみ許される強引な方法でprivateメンバ変数の参照を取得 + const obj = (service as any).adB2cService as AdB2cService; + if (overrides.createUser) { + Object.defineProperty(obj, obj.createUser.name, { + value: overrides.createUser, + writable: true, + }); + } + if (overrides.deleteUser) { + Object.defineProperty(obj, obj.deleteUser.name, { + value: overrides.deleteUser, + writable: true, + }); + } +}; + +/** + * sendgridServiceのモックを作成して、TServiceが依存するサービス(sendgridService)の参照を上書きする + * ※ serviceに指定するオブジェクトは`sendgridService: SendgridService`メンバ変数を持つ必要がある + * @param service 上書きしたいTService + * @param overrides sendgridServiceの各種メソッドのモックが返す値(省略した場合は既定のダミーの値) + */ +export const overrideSendgridService = ( + service: TService, + overrides: { + createMailContentFromEmailConfirm?: ( + context: Context, + accountId: number, + userId: number, + email: string, + ) => Promise<{ subject: string; text: string; html: string }>; + createMailContentFromEmailConfirmForNormalUser?: ( + accountId: number, + userId: number, + email: string, + ) => Promise<{ subject: string; text: string; html: string }>; + sendMail?: ( + context: Context, + to: string, + from: string, + subject: string, + text: string, + html: string, + ) => Promise; + }, +): void => { + // テストコードでのみ許される強引な方法でprivateメンバ変数の参照を取得 + const obj = (service as any).sendgridService as SendGridService; + if (overrides.sendMail) { + Object.defineProperty(obj, obj.sendMail.name, { + value: overrides.sendMail, + writable: true, + }); + } else { + // [重要] + // sendMailだけは外部に対する送信を行ってしまう & 失敗によりメールアドレス自体の信頼度が変動してしまうため、 + // overrideした場合には"必ず"偽物の呼び出しになるようにしておく + Object.defineProperty(obj, obj.sendMail.name, { + value: async () => { + return; + }, + writable: true, + }); + } + + if (overrides.createMailContentFromEmailConfirm) { + Object.defineProperty(obj, obj.createMailContentFromEmailConfirm.name, { + value: overrides.createMailContentFromEmailConfirm, + writable: true, + }); + } + + if (overrides.createMailContentFromEmailConfirmForNormalUser) { + Object.defineProperty( + obj, + obj.createMailContentFromEmailConfirmForNormalUser.name, + { + value: overrides.createMailContentFromEmailConfirmForNormalUser, + writable: true, + }, + ); + } +}; + +/** + * usersRepositoryのモックを作成して、TServiceが依存するサービス(usersRepositoryService)の参照を上書きする + * ※ serviceに指定するオブジェクトは`usersRepository: UsersRepositoryService`メンバ変数を持つ必要がある + * @param service 上書きしたいTService + * @param overrides usersRepositoryの各種メソッドのモックが返す値(省略した場合は既定のダミーの値) + */ +export const overrideUsersRepositoryService = ( + service: TService, + overrides: { + createNormalUser?: (user: newUser) => Promise; + deleteNormalUser?: (userId: number) => Promise; + }, +): void => { + // テストコードでのみ許される強引な方法でprivateメンバ変数の参照を取得 + const obj = (service as any).usersRepository as UsersRepositoryService; + if (overrides.createNormalUser) { + Object.defineProperty(obj, obj.createNormalUser.name, { + value: overrides.createNormalUser, + writable: true, + }); + } + if (overrides.deleteNormalUser) { + Object.defineProperty(obj, obj.deleteNormalUser.name, { + value: overrides.deleteNormalUser, + writable: true, + }); + } +}; + +/** + * blobStorageServiceのモックを作成して、TServiceが依存するサービス(blobStorageService)の参照を上書きする + * ※ serviceに指定するオブジェクトは`blobstorageService: blobStorageService`メンバ変数を持つ必要がある + * @param service 上書きしたいTService + * @param overrides blobStorageServiceの各種メソッドのモックが返す値(省略した場合は既定のダミーの値) + */ +export const overrideBlobstorageService = ( + service: TService, + overrides: { + createContainer?: ( + context: Context, + accountId: number, + country: string, + ) => Promise; + deleteContainer?: ( + context: Context, + accountId: number, + country: string, + ) => Promise; + }, +): void => { + // テストコードでのみ許される強引な方法でprivateメンバ変数の参照を取得 + const obj = (service as any).blobStorageService as BlobstorageService; + if (overrides.createContainer) { + Object.defineProperty(obj, obj.createContainer.name, { + value: overrides.createContainer, + writable: true, + }); + } + if (overrides.deleteContainer) { + Object.defineProperty(obj, obj.deleteContainer.name, { + value: overrides.deleteContainer, + writable: true, + }); + } +}; + +/** + * accountsRepositoryのモックを作成して、TServiceが依存するサービス(AccountsRepositoryService)の参照を上書きする + * ※ serviceに指定するオブジェクトは`accountsRepository: AccountsRepositoryService`メンバ変数を持つ必要がある + * @param service 上書きしたいTService + * @param overrides accountsRepositoryの各種メソッドのモックが返す値(省略した場合は本物のメソッドが呼ばれる) + */ +export const overrideAccountsRepositoryService = ( + service: TService, + overrides: { + createAccount?: ( + companyName: string, + country: string, + dealerAccountId: number | undefined, + tier: number, + adminExternalUserId: string, + adminUserRole: string, + adminUserAcceptedTermsVersion: string, + ) => Promise<{ newAccount: Account; adminUser: User }>; + deleteAccount?: (accountId: number, userId: number) => Promise; + }, +): void => { + // テストコードでのみ許される強引な方法でprivateメンバ変数の参照を取得 + const obj = (service as any).accountRepository as AccountsRepositoryService; + if (overrides.deleteAccount) { + Object.defineProperty(obj, obj.deleteAccount.name, { + value: overrides.deleteAccount, + writable: true, + }); + } + if (overrides.createAccount) { + Object.defineProperty(obj, obj.createAccount.name, { + value: overrides.createAccount, + writable: true, + }); + } +}; diff --git a/dictation_server/src/common/validators/admin.validator.ts b/dictation_server/src/common/validators/admin.validator.ts new file mode 100644 index 0000000..296ba7e --- /dev/null +++ b/dictation_server/src/common/validators/admin.validator.ts @@ -0,0 +1,31 @@ +import { registerDecorator, ValidationOptions } from 'class-validator'; + +export const IsAdminPasswordvalid = (validationOptions?: ValidationOptions) => { + return (object: any, propertyName: string) => { + registerDecorator({ + name: 'IsAdminPasswordvalid', + target: object.constructor, + propertyName: propertyName, + constraints: [], + options: validationOptions, + validator: { + validate: (value: string) => { + // 8文字~64文字でなければ早期に不合格 + const minLength = 8; + const maxLength = 64; + if (value.length < minLength || value.length > maxLength) { + return false; + } + + // 英字の大文字、英字の小文字、アラビア数字、記号(@#$%^&*\-_+=[]{}|\:',.?/`~"();!)から2種類以上組み合わせ + const charaTypePattern = + /^((?=.*[a-z])(?=.*[A-Z])|(?=.*[a-z])(?=.*[\d])|(?=.*[a-z])(?=.*[@#$%^&*\\\-_+=\[\]{}|:',.?\/`~"();!])|(?=.*[A-Z])(?=.*[\d])|(?=.*[A-Z])(?=.*[@#$%^&*\\\-_+=\[\]{}|:',.?\/`~"();!])|(?=.*[\d])(?=.*[@#$%^&*\\\-_+=\[\]{}|:',.?\/`~"();!]))[a-zA-Z\d@#$%^&*\\\-_+=\[\]{}|:',.?\/`~"();!]/; + return new RegExp(charaTypePattern).test(value); + }, + defaultMessage: () => { + return 'Admin password rule not satisfied'; + }, + }, + }); + }; +}; diff --git a/dictation_server/src/constants/index.ts b/dictation_server/src/constants/index.ts index 1a0852e..cdf2352 100644 --- a/dictation_server/src/constants/index.ts +++ b/dictation_server/src/constants/index.ts @@ -119,6 +119,15 @@ export const LICENSE_ALLOCATED_STATUS = { REUSABLE: 'Reusable', DELETED: 'Deleted', } as const; +/** + * 切り替え元種別 + * @const {string[]} + */ +export const SWITCH_FROM_TYPE = { + NONE: 'NONE', + CARD: 'CARD', + TRIAL: 'TRIAL', +} as const; /** * ライセンスの期限切れが近いと見なす日数のしきい値 @@ -126,6 +135,12 @@ export const LICENSE_ALLOCATED_STATUS = { */ export const LICENSE_EXPIRATION_THRESHOLD_DAYS = 14; +/** + * ライセンスの有効期間 + * @const {number} + */ +export const LICENSE_EXPIRATION_DAYS = 365; + /** * カードライセンスの桁数 * @const {number} @@ -198,3 +213,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/accounts/accounts.controller.ts b/dictation_server/src/features/accounts/accounts.controller.ts index 70dbc76..1fec4f0 100644 --- a/dictation_server/src/features/accounts/accounts.controller.ts +++ b/dictation_server/src/features/accounts/accounts.controller.ts @@ -33,6 +33,8 @@ import { IssueLicenseRequest, IssueLicenseResponse, GetDealersResponse, + CreateTypistGroupResponse, + CreateTypistGroupRequest, } from './types/types'; import { USER_ROLES, ADMIN_ROLES, TIERS } from '../../constants'; import { AuthGuard } from '../../common/guards/auth/authguards'; @@ -40,7 +42,8 @@ import { RoleGuard } from '../../common/guards/role/roleguards'; import { retrieveAuthorizationToken } from '../../common/http/helper'; import { AccessToken } from '../../common/token'; import jwt from 'jsonwebtoken'; -import { Context } from '../../common/log'; +import { makeContext } from '../../common/log'; +import { v4 as uuidv4 } from 'uuid'; @ApiTags('accounts') @Controller('accounts') @@ -80,7 +83,10 @@ export class AccountsController { } = body; const role = USER_ROLES.NONE; + const context = makeContext(uuidv4()); + await this.accountService.createAccount( + context, companyName, country, dealerAccountId, @@ -239,6 +245,46 @@ export class AccountsController { return { typistGroups }; } + @ApiResponse({ + status: HttpStatus.OK, + type: CreateTypistGroupResponse, + description: '成功時のレスポンス', + }) + @ApiResponse({ + status: HttpStatus.BAD_REQUEST, + description: 'グループ名が空の場合/ユーザーが存在しない場合', + type: ErrorResponse, + }) + @ApiResponse({ + status: HttpStatus.UNAUTHORIZED, + description: '認証エラー', + type: ErrorResponse, + }) + @ApiResponse({ + status: HttpStatus.INTERNAL_SERVER_ERROR, + description: '想定外のサーバーエラー', + type: ErrorResponse, + }) + @ApiOperation({ + operationId: 'createTypistGroup', + description: + 'ログインしているユーザーのアカウント配下にタイピストグループを追加します', + }) + @ApiBearerAuth() + @UseGuards(AuthGuard) + @UseGuards(RoleGuard.requireds({ roles: [ADMIN_ROLES.ADMIN] })) + @Post('typist-groups') + async createTypistGroup( + @Req() req: Request, + @Body() body: CreateTypistGroupRequest, + ): Promise { + // アクセストークン取得 + const accessToken = retrieveAuthorizationToken(req); + const payload = jwt.decode(accessToken, { json: true }) as AccessToken; + + return {}; + } + @Post('partner') @ApiResponse({ status: HttpStatus.OK, @@ -277,7 +323,10 @@ export class AccountsController { const accessToken = retrieveAuthorizationToken(req); const payload = jwt.decode(accessToken, { json: true }) as AccessToken; + const context = makeContext(payload.userId); + await this.accountService.createPartnerAccount( + context, companyName, country, email, @@ -401,12 +450,17 @@ export class AccountsController { console.log(body); const { orderedAccountId, poNumber } = body; - /*await this.licensesService.issueLicense( - orderedAccountId + const token = retrieveAuthorizationToken(req); + const accessToken = jwt.decode(token, { json: true }) as AccessToken; + + const context = makeContext(accessToken.userId); + await this.accountService.issueLicense( + context, + orderedAccountId, + accessToken.userId, + accessToken.tier, poNumber, ); - */ - return {}; } diff --git a/dictation_server/src/features/accounts/accounts.module.ts b/dictation_server/src/features/accounts/accounts.module.ts index a706b56..02991ab 100644 --- a/dictation_server/src/features/accounts/accounts.module.ts +++ b/dictation_server/src/features/accounts/accounts.module.ts @@ -7,6 +7,7 @@ import { AccountsController } from './accounts.controller'; import { AccountsService } from './accounts.service'; import { AdB2cModule } from '../../gateways/adb2c/adb2c.module'; import { UserGroupsRepositoryModule } from '../../repositories/user_groups/user_groups.repository.module'; +import { BlobstorageModule } from '../../gateways/blobstorage/blobstorage.module'; @Module({ imports: [ @@ -16,6 +17,7 @@ import { UserGroupsRepositoryModule } from '../../repositories/user_groups/user_ UserGroupsRepositoryModule, SendGridModule, AdB2cModule, + BlobstorageModule, ], controllers: [AccountsController], providers: [AccountsService], diff --git a/dictation_server/src/features/accounts/accounts.service.spec.ts b/dictation_server/src/features/accounts/accounts.service.spec.ts index c4925e8..1879e68 100644 --- a/dictation_server/src/features/accounts/accounts.service.spec.ts +++ b/dictation_server/src/features/accounts/accounts.service.spec.ts @@ -2,6 +2,7 @@ import { HttpException, HttpStatus } from '@nestjs/common'; import { makeErrorResponse } from '../../common/error/makeErrorResponse'; import { makeAccountsServiceMock, + makeBlobStorageServiceMockValue, makeDefaultAccountsRepositoryMockValue, makeDefaultAdB2cMockValue, makeDefaultLicensesRepositoryMockValue, @@ -14,11 +15,1414 @@ import { createAccount, createLicense, createLicenseOrder, + createUser, + createLicenseSetExpiryDateAndStatus, + getAccount, + getUserFromExternalID, + getAccounts, + getUsers, + getSortCriteria, + createAccountAndAdminUser, } from './test/utility'; import { DataSource } from 'typeorm'; import { makeTestingModule } from '../../common/test/modules'; import { AccountsService } from './accounts.service'; +import { Context, makeContext } from '../../common/log'; import { TIERS } from '../../constants'; +import { License } from '../../repositories/licenses/entity/license.entity'; +import { + overrideAccountsRepositoryService, + overrideAdB2cService, + overrideBlobstorageService, + overrideSendgridService, +} from '../../common/test/overrides'; +import { AdB2cService } from '../../gateways/adb2c/adb2c.service'; +import { BlobstorageService } from '../../gateways/blobstorage/blobstorage.service'; + +describe('createAccount', () => { + let source: DataSource = null; + beforeEach(async () => { + source = new DataSource({ + type: 'sqlite', + database: ':memory:', + logging: false, + entities: [__dirname + '/../../**/*.entity{.ts,.js}'], + synchronize: true, // trueにすると自動的にmigrationが行われるため注意 + }); + return source.initialize(); + }); + + afterEach(async () => { + await source.destroy(); + source = null; + }); + + it('アカウントを作成できる', async () => { + const module = await makeTestingModule(source); + const service = module.get(AccountsService); + + const externalId = 'test_external_id'; + const companyName = 'test_company_name'; + const country = 'US'; + const dealerAccountId = 1; + const email = 'dummy@example.com'; + const password = 'dummy_password'; + const username = 'dummy_username'; + const role = 'none'; + const acceptedTermsVersion = '1.0.0'; + + overrideAdB2cService(service, { + createUser: async () => { + return { sub: externalId }; + }, + }); + + overrideSendgridService(service, { + sendMail: async () => { + return; + }, + createMailContentFromEmailConfirm: async () => { + return { html: '', text: '', subject: '' }; + }, + }); + overrideBlobstorageService(service, { + createContainer: async () => { + return; + }, + }); + + const { accountId, externalUserId, userId } = await service.createAccount( + makeContext('uuid'), + companyName, + country, + dealerAccountId, + email, + password, + username, + role, + acceptedTermsVersion, + ); + // 作成したアカウントのIDが返ってくるか確認 + expect(accountId).toBe(1); + expect(externalUserId).toBe(externalId); + expect(userId).toBe(1); + + // DB内が想定通りになっているか確認 + const account = await getAccount(source, accountId); + const user = await getUserFromExternalID(source, externalUserId); + expect(account.company_name).toBe(companyName); + expect(account.country).toBe(country); + expect(account.parent_account_id).toBe(dealerAccountId); + expect(account.tier).toBe(TIERS.TIER5); + expect(account.primary_admin_user_id).toBe(user.id); + expect(account.secondary_admin_user_id).toBe(null); + expect(user.accepted_terms_version).toBe(acceptedTermsVersion); + expect(user.account_id).toBe(accountId); + expect(user.role).toBe(role); + }); + + it('アカウントを作成がAzure AD B2Cへの通信失敗によって失敗すると500エラーが発生する', async () => { + const module = await makeTestingModule(source); + const service = module.get(AccountsService); + + overrideAdB2cService(service, { + createUser: async () => { + throw new Error(); + }, + }); + + overrideSendgridService(service, { + sendMail: async () => { + return; + }, + createMailContentFromEmailConfirm: async () => { + return { html: '', text: '', subject: '' }; + }, + }); + + const companyName = 'test_company_name'; + const country = 'US'; + const dealerAccountId = 1; + const email = 'dummy@example.com'; + const password = 'dummy_password'; + const username = 'dummy_username'; + const role = 'admin none'; + const acceptedTermsVersion = '1.0.0'; + + overrideAdB2cService(service, { + createUser: async () => { + throw new Error(); + }, + }); + overrideSendgridService(service, {}); + overrideBlobstorageService(service, {}); + + try { + await service.createAccount( + makeContext('uuid'), + companyName, + country, + dealerAccountId, + email, + password, + username, + role, + acceptedTermsVersion, + ); + } catch (e) { + if (e instanceof HttpException) { + expect(e.getStatus()).toBe(HttpStatus.INTERNAL_SERVER_ERROR); + expect(e.getResponse()).toEqual(makeErrorResponse('E009999')); + } else { + fail(); + } + } + + // DB内が想定通りになっているか確認 + const accounts = await getAccounts(source); + expect(accounts.length).toBe(0); + const users = await getUsers(source); + expect(users.length).toBe(0); + }); + + it('アカウントを作成がメールアドレス重複によって失敗すると400エラーが発生する', async () => { + const module = await makeTestingModule(source); + const service = module.get(AccountsService); + + overrideAdB2cService(service, { + createUser: async () => { + // EmailのConflictエラーを返す + return { reason: 'email', message: 'dummy' }; + }, + }); + + overrideSendgridService(service, { + sendMail: async () => { + return; + }, + createMailContentFromEmailConfirm: async () => { + return { html: '', text: '', subject: '' }; + }, + }); + + const companyName = 'test_company_name'; + const country = 'US'; + const dealerAccountId = 1; + const email = 'dummy@example.com'; + const password = 'dummy_password'; + const username = 'dummy_username'; + const role = 'admin none'; + const acceptedTermsVersion = '1.0.0'; + + overrideAdB2cService(service, { + createUser: async () => { + // EmailのConflictエラーを返す + return { reason: 'email', message: 'dummy' }; + }, + }); + overrideSendgridService(service, {}); + overrideBlobstorageService(service, {}); + + try { + await service.createAccount( + makeContext('uuid'), + companyName, + country, + dealerAccountId, + email, + password, + username, + role, + acceptedTermsVersion, + ); + } catch (e) { + if (e instanceof HttpException) { + expect(e.getStatus()).toBe(HttpStatus.BAD_REQUEST); + expect(e.getResponse()).toEqual(makeErrorResponse('E010301')); + } else { + fail(); + } + } + + // DB内が想定通りになっているか確認 + const accounts = await getAccounts(source); + expect(accounts.length).toBe(0); + const users = await getUsers(source); + expect(users.length).toBe(0); + }); + it('アカウントを作成がDBへの通信失敗によって500エラーが発生した場合、リカバリ処理としてADB2Cユーザーを削除され、500エラーが返却される', async () => { + const module = await makeTestingModule(source); + const service = module.get(AccountsService); + const b2cService = module.get(AdB2cService); + const externalId = 'test_external_id'; + const companyName = 'test_company_name'; + const country = 'US'; + const dealerAccountId = 1; + const email = 'dummy@example.com'; + const password = 'dummy_password'; + const username = 'dummy_username'; + const role = 'none'; + const acceptedTermsVersion = '1.0.0'; + + overrideAdB2cService(service, { + createUser: async () => { + return { sub: externalId }; + }, + deleteUser: jest.fn(), + }); + overrideSendgridService(service, {}); + + overrideAccountsRepositoryService(service, { + createAccount: async () => { + throw new Error(); + }, + }); + + try { + await service.createAccount( + makeContext('uuid'), + companyName, + country, + dealerAccountId, + email, + password, + username, + role, + acceptedTermsVersion, + ); + } catch (e) { + if (e instanceof HttpException) { + expect(e.getStatus()).toBe(HttpStatus.INTERNAL_SERVER_ERROR); + expect(e.getResponse()).toEqual(makeErrorResponse('E009999')); + } else { + fail(); + } + } + // DB内が想定通りになっているか確認 + // DBのデータ作成で失敗しているので、DB内は空 + const accounts = await getAccounts(source); + expect(accounts.length).toBe(0); + const users = await getUsers(source); + expect(users.length).toBe(0); + const sortCriteria = await getSortCriteria(source); + expect(sortCriteria.length).toBe(0); + // ADB2Cユーザー削除メソッドが呼ばれているか確認 + expect(b2cService.deleteUser).toBeCalledWith( + externalId, + makeContext('uuid'), + ); + }); + it('アカウントを作成がDBへの通信失敗によって500エラーが発生した場合、リカバリ処理が実行されるが、ADB2Cユーザー削除で失敗した場合、500エラーが返却される', async () => { + const module = await makeTestingModule(source); + const service = module.get(AccountsService); + const b2cService = module.get(AdB2cService); + const externalId = 'test_external_id'; + const companyName = 'test_company_name'; + const country = 'US'; + const dealerAccountId = 1; + const email = 'dummy@dummy.dummy'; + const password = 'dummy_password'; + const username = 'dummy_username'; + const role = 'none'; + const acceptedTermsVersion = '1.0.0'; + + overrideAdB2cService(service, { + createUser: async () => { + return { sub: externalId }; + }, + deleteUser: jest.fn().mockRejectedValue(new Error()), + }); + overrideSendgridService(service, {}); + + overrideAccountsRepositoryService(service, { + createAccount: async () => { + throw new Error(); + }, + }); + + try { + await service.createAccount( + makeContext('uuid'), + companyName, + country, + dealerAccountId, + email, + password, + username, + role, + acceptedTermsVersion, + ); + } catch (e) { + if (e instanceof HttpException) { + expect(e.getStatus()).toBe(HttpStatus.INTERNAL_SERVER_ERROR); + expect(e.getResponse()).toEqual(makeErrorResponse('E009999')); + } else { + fail(); + } + } + // DB内が想定通りになっているか確認 + // DBのデータ作成で失敗しているので、DB内は空 + const accounts = await getAccounts(source); + expect(accounts.length).toBe(0); + const users = await getUsers(source); + expect(users.length).toBe(0); + const sortCriteria = await getSortCriteria(source); + expect(sortCriteria.length).toBe(0); + // ADB2Cユーザー削除メソッドが呼ばれているか確認 + expect(b2cService.deleteUser).toBeCalledWith( + externalId, + makeContext('uuid'), + ); + }); + + it('アカウントを作成がBlobStorageへの通信失敗によって500エラーが発生した場合、リカバリ処理としてADB2C,DB上のデータが削除され、500エラーが返却される', async () => { + const module = await makeTestingModule(source); + const service = module.get(AccountsService); + const b2cService = module.get(AdB2cService); + b2cService.deleteUser = jest.fn(); // リカバリ処理の確認のため、deleteUserをモック化 + const externalId = 'test_external_id'; + const companyName = 'test_company_name'; + const country = 'US'; + const dealerAccountId = 1; + const email = 'dummy@dummy.dummy'; + const password = 'dummy_password'; + const username = 'dummy_username'; + const role = 'none'; + const acceptedTermsVersion = '1.0.0'; + + overrideAdB2cService(service, { + createUser: async () => { + return { sub: externalId }; + }, + deleteUser: async () => { + return; + }, + }); + overrideSendgridService(service, {}); + overrideBlobstorageService(service, { + createContainer: async () => { + throw new Error(); + }, + }); + + try { + await service.createAccount( + makeContext('uuid'), + companyName, + country, + dealerAccountId, + email, + password, + username, + role, + acceptedTermsVersion, + ); + } catch (e) { + if (e instanceof HttpException) { + expect(e.getStatus()).toBe(HttpStatus.INTERNAL_SERVER_ERROR); + expect(e.getResponse()).toEqual(makeErrorResponse('E009999')); + } else { + fail(); + } + } + // DB内が想定通りになっているか確認 + // リカバリ処理が走っているため、アカウント・ユーザーは削除されている + const accounts = await getAccounts(source); + expect(accounts.length).toBe(0); + const users = await getUsers(source); + expect(users.length).toBe(0); + const sortCriteria = await getSortCriteria(source); + expect(sortCriteria.length).toBe(0); + // ADB2Cユーザー削除メソッドが呼ばれているか確認 + expect(b2cService.deleteUser).toBeCalledWith( + externalId, + makeContext('uuid'), + ); + }); + + it('アカウントを作成がBlobStorageへの通信失敗によって500エラーが発生した場合、リカバリ処理が実行されるが、そのリカバリ処理に失敗した場合、500エラーが返却される', async () => { + const module = await makeTestingModule(source); + const service = module.get(AccountsService); + const b2cService = module.get(AdB2cService); + const externalId = 'test_external_id'; + const companyName = 'test_company_name'; + const country = 'US'; + const dealerAccountId = 1; + const email = 'dummy@dummy.dummy'; + const password = 'dummy_password'; + const username = 'dummy_username'; + const role = 'none'; + const acceptedTermsVersion = '1.0.0'; + + overrideAdB2cService(service, { + createUser: async () => { + return { sub: externalId }; + }, + deleteUser: jest.fn().mockRejectedValue(new Error()), + }); + overrideSendgridService(service, {}); + overrideBlobstorageService(service, { + createContainer: async () => { + throw new Error(); + }, + }); + overrideAccountsRepositoryService(service, { + deleteAccount: async () => { + throw new Error(); + }, + }); + + try { + await service.createAccount( + makeContext('uuid'), + companyName, + country, + dealerAccountId, + email, + password, + username, + role, + acceptedTermsVersion, + ); + } catch (e) { + if (e instanceof HttpException) { + expect(e.getStatus()).toBe(HttpStatus.INTERNAL_SERVER_ERROR); + expect(e.getResponse()).toEqual(makeErrorResponse('E009999')); + } else { + fail(); + } + } + // DB内が想定通りになっているか確認 + // DB上のデータのリカバリ処理に失敗したため、DB上のデータは削除されない + const accounts = await getAccounts(source); + expect(accounts.length).toBe(1); + const users = await getUsers(source); + expect(users.length).toBe(1); + const sortCriteria = await getSortCriteria(source); + expect(sortCriteria.length).toBe(1); + // ADB2Cユーザー削除メソッドが呼ばれているか確認 + expect(b2cService.deleteUser).toBeCalledWith( + externalId, + makeContext('uuid'), + ); + }); + + it('アカウントを作成がSendGridへの通信失敗によって500エラーが発生した場合、リカバリ処理としてADB2C,DB上のデータとBlobストレージのコンテナが削除され、500エラーが返却される', async () => { + const module = await makeTestingModule(source); + const service = module.get(AccountsService); + const b2cService = module.get(AdB2cService); + const blobstorageService = + module.get(BlobstorageService); + const externalId = 'test_external_id'; + const companyName = 'test_company_name'; + const country = 'US'; + const dealerAccountId = 1; + const email = 'dummy@dummy.dummy'; + const password = 'dummy_password'; + const username = 'dummy_username'; + const role = 'none'; + const acceptedTermsVersion = '1.0.0'; + + overrideAdB2cService(service, { + createUser: async ( + _context: Context, + _email: string, + _password: string, + _username: string, + ) => { + // ユーザー作成時に指定したパラメータが正しく渡されていることを確認 + expect(email).toEqual(_email); + expect(username).toEqual(_username); + + return { sub: externalId }; + }, + deleteUser: jest.fn(), + }); + overrideSendgridService(service, { + sendMail: async () => { + throw new Error(); + }, + createMailContentFromEmailConfirm: async () => { + return { + html: 'dummy_html', + subject: 'dummy_subject', + text: 'dummy_text', + }; + }, + }); + overrideBlobstorageService(service, { + createContainer: async () => { + return; + }, + deleteContainer: jest.fn(), + }); + overrideAccountsRepositoryService(service, {}); + + try { + await service.createAccount( + makeContext('uuid'), + companyName, + country, + dealerAccountId, + email, + password, + username, + role, + acceptedTermsVersion, + ); + } catch (e) { + if (e instanceof HttpException) { + expect(e.getStatus()).toBe(HttpStatus.INTERNAL_SERVER_ERROR); + expect(e.getResponse()).toEqual(makeErrorResponse('E009999')); + } else { + fail(); + } + } + // DB内が想定通りになっているか確認 + // リカバリ処理によってADB2C,DB上のデータとBlobストレージのコンテナが削除される + const accounts = await getAccounts(source); + expect(accounts.length).toBe(0); + const users = await getUsers(source); + expect(users.length).toBe(0); + const sortCriteria = await getSortCriteria(source); + expect(sortCriteria.length).toBe(0); + // ADB2Cユーザー削除メソッドが呼ばれているか確認 + expect(b2cService.deleteUser).toBeCalledWith( + externalId, + makeContext('uuid'), + ); + // Blobストレージのコンテナ削除メソッドが呼ばれているか確認 + expect(blobstorageService.deleteContainer).toBeCalledWith( + makeContext('uuid'), + 1, //新規作成したアカウントのID + country, + ); + }); + + it('アカウントを作成がSendGridへの通信失敗によって500エラーが発生した場合、リカバリ処理が実行されるが、そのリカバリ処理に失敗した場合、500エラーが返却される', async () => { + const module = await makeTestingModule(source); + const service = module.get(AccountsService); + const b2cService = module.get(AdB2cService); + const blobstorageService = + module.get(BlobstorageService); + const externalId = 'test_external_id'; + const companyName = 'test_company_name'; + const country = 'US'; + const dealerAccountId = 1; + const email = 'dummy@dummy.dummy'; + const password = 'dummy_password'; + const username = 'dummy_username'; + const role = 'none'; + const acceptedTermsVersion = '1.0.0'; + + overrideAdB2cService(service, { + createUser: async () => { + return { sub: externalId }; + }, + deleteUser: jest.fn().mockRejectedValue(new Error()), + }); + overrideSendgridService(service, { + sendMail: async () => { + throw new Error(); + }, + createMailContentFromEmailConfirm: async () => { + return { + html: 'dummy_html', + subject: 'dummy_subject', + text: 'dummy_text', + }; + }, + }); + overrideBlobstorageService(service, { + createContainer: async () => { + return; + }, + deleteContainer: jest + .fn() + .mockRejectedValue(new Error('BlobStorage Error')), + }); + overrideAccountsRepositoryService(service, { + deleteAccount: async () => { + throw new Error(); + }, + }); + + try { + await service.createAccount( + makeContext('uuid'), + companyName, + country, + dealerAccountId, + email, + password, + username, + role, + acceptedTermsVersion, + ); + } catch (e) { + if (e instanceof HttpException) { + expect(e.getStatus()).toBe(HttpStatus.INTERNAL_SERVER_ERROR); + expect(e.getResponse()).toEqual(makeErrorResponse('E009999')); + } else { + fail(); + } + } + // DB内が想定通りになっているか確認 + // リカバリ処理によってADB2C,DB上のデータとBlobストレージのコンテナが削除されない + const accounts = await getAccounts(source); + expect(accounts.length).toBe(1); + const users = await getUsers(source); + expect(users.length).toBe(1); + const sortCriteria = await getSortCriteria(source); + expect(sortCriteria.length).toBe(1); + // ADB2Cユーザー削除メソッドが呼ばれているか確認 + expect(b2cService.deleteUser).toBeCalledWith( + externalId, + makeContext('uuid'), + ); + // Blobストレージのコンテナ削除メソッドが呼ばれているか確認 + expect(blobstorageService.deleteContainer).toBeCalledWith( + makeContext('uuid'), + 1, //新規作成したアカウントのID + country, + ); + }); +}); + +describe('createPartnerAccount', () => { + let source: DataSource = null; + beforeEach(async () => { + source = new DataSource({ + type: 'sqlite', + database: ':memory:', + logging: false, + entities: [__dirname + '/../../**/*.entity{.ts,.js}'], + synchronize: true, // trueにすると自動的にmigrationが行われるため注意 + }); + return source.initialize(); + }); + + afterEach(async () => { + await source.destroy(); + source = null; + }); + + it('パートナーを追加できる', async () => { + const module = await makeTestingModule(source); + const service = module.get(AccountsService); + const adminExternalId = 'ADMIN0001'; + + // 第一階層のアカウントを作成 + const { accountId: parentAccountId, tier } = + await createAccountAndAdminUser(source, adminExternalId); + + const context = makeContext('uuid'); + const companyName = 'test_company_name'; + const country = 'US'; + const email = 'partner@example.com'; + const adminName = 'partner_admin'; + const pertnerExternalId = 'PARTNER0001'; + + overrideAdB2cService(service, { + createUser: async () => { + return { sub: pertnerExternalId }; + }, + }); + + overrideSendgridService(service, { + createMailContentFromEmailConfirmForNormalUser: async () => { + return { html: '', text: '', subject: '' }; + }, + sendMail: async () => { + return; + }, + }); + + overrideBlobstorageService(service, { + createContainer: async () => { + return; + }, + }); + + // DB上に用意されたデータが想定通りであるか確認 + { + const accounts = await getAccounts(source); + expect(accounts.length).toBe(1); + } + + const { accountId } = await service.createPartnerAccount( + context, + companyName, + country, + email, + adminName, + adminExternalId, + tier, + ); + + // DB上に作成されたデータが想定通りであるか確認 + { + const accounts = await getAccounts(source); + expect(accounts.length).toBe(2); + + const createdUser = await getUserFromExternalID( + source, + pertnerExternalId, + ); + const createdAccount = await getAccount(source, accountId); + expect(createdAccount.company_name).toBe(companyName); + expect(createdAccount.country).toBe(country); + expect(createdAccount.parent_account_id).toBe(parentAccountId); + expect(createdAccount.tier).toBe(2); + expect(createdAccount.primary_admin_user_id).toBe(createdUser.id); + expect(createdAccount.secondary_admin_user_id).toBe(null); + } + }); + + it('Azure AD B2Cへの接続に失敗した結果アカウントの追加に失敗した場合、エラーとなる(500エラー)', async () => { + const module = await makeTestingModule(source); + const service = module.get(AccountsService); + const adminExternalId = 'ADMIN0001'; + + // 第一階層のアカウントを作成 + const { tier } = await createAccountAndAdminUser(source, adminExternalId); + + const context = makeContext('uuid'); + const companyName = 'test_company_name'; + const country = 'US'; + const email = 'partner@example.com'; + const adminName = 'partner_admin'; + + overrideAdB2cService(service, { + createUser: async () => { + throw new Error(); + }, + }); + + overrideSendgridService(service, { + createMailContentFromEmailConfirmForNormalUser: async () => { + return { html: '', text: '', subject: '' }; + }, + sendMail: async () => { + return; + }, + }); + + overrideBlobstorageService(service, { + createContainer: async () => { + return; + }, + }); + + // DB上に用意されたデータが想定通りであるか確認 + { + const accounts = await getAccounts(source); + expect(accounts.length).toBe(1); + const users = await getUsers(source); + expect(users.length).toBe(1); + } + + try { + await service.createPartnerAccount( + context, + companyName, + country, + email, + adminName, + adminExternalId, + tier, + ); + } catch (e) { + if (e instanceof HttpException) { + expect(e.getStatus()).toBe(HttpStatus.INTERNAL_SERVER_ERROR); + expect(e.getResponse()).toEqual(makeErrorResponse('E009999')); + } else { + fail(); + } + } + + // DB上に作成されたデータが想定通りであるか確認 + { + const accounts = await getAccounts(source); + expect(accounts.length).toBe(1); + const users = await getUsers(source); + expect(users.length).toBe(1); + } + }); + + it('DBへの通信失敗によって500エラーが発生した場合、リカバリ処理としてADB2Cユーザーを削除され、500エラーが返却される', async () => { + const module = await makeTestingModule(source); + const service = module.get(AccountsService); + const b2cService = module.get(AdB2cService); + const adminExternalId = 'ADMIN0001'; + + // 第一階層のアカウントを作成 + const { tier } = await createAccountAndAdminUser(source, adminExternalId); + + const context = makeContext('uuid'); + const companyName = 'test_company_name'; + const country = 'US'; + const email = 'partner@example.com'; + const adminName = 'partner_admin'; + const partnerExternalId = 'partner_external_id'; + + overrideAdB2cService(service, { + createUser: async () => { + return { sub: partnerExternalId }; + }, + deleteUser: jest.fn(), + }); + + overrideSendgridService(service, { + createMailContentFromEmailConfirmForNormalUser: async () => { + return { html: '', text: '', subject: '' }; + }, + sendMail: async () => { + return; + }, + }); + overrideAccountsRepositoryService(service, { + createAccount: async () => { + throw new Error('DB Error'); + }, + }); + + overrideBlobstorageService(service, { + createContainer: async () => { + return; + }, + }); + + // DB上に用意されたデータが想定通りであるか確認 + { + const accounts = await getAccounts(source); + expect(accounts.length).toBe(1); + const users = await getUsers(source); + expect(users.length).toBe(1); + } + + try { + await service.createPartnerAccount( + context, + companyName, + country, + email, + adminName, + adminExternalId, + tier, + ); + } catch (e) { + if (e instanceof HttpException) { + expect(e.getStatus()).toBe(HttpStatus.INTERNAL_SERVER_ERROR); + expect(e.getResponse()).toEqual(makeErrorResponse('E009999')); + } else { + fail(); + } + } + + // DB上に作成されたデータが想定通りであるか確認 + { + const accounts = await getAccounts(source); + expect(accounts.length).toBe(1); + expect(accounts[0].tier).toBe(1); + const users = await getUsers(source); + expect(users.length).toBe(1); + expect(users[0].external_id).toBe(adminExternalId); + // ADB2Cユーザー削除メソッドが呼ばれているか確認 + expect(b2cService.deleteUser).toBeCalledWith(partnerExternalId, context); + } + }); + + it('DBへの通信失敗によって500エラーが発生した場合、リカバリ処理が実行されるが、ADB2Cユーザー削除で失敗した場合、500エラーが返却される', async () => { + const module = await makeTestingModule(source); + const service = module.get(AccountsService); + const b2cService = module.get(AdB2cService); + const adminExternalId = 'ADMIN0001'; + + // 第一階層のアカウントを作成 + const { tier } = await createAccountAndAdminUser(source, adminExternalId); + + const context = makeContext('uuid'); + const companyName = 'test_company_name'; + const country = 'US'; + const email = 'partner@example.com'; + const adminName = 'partner_admin'; + const partnerExternalId = 'partner_external_id'; + + overrideAdB2cService(service, { + createUser: async () => { + return { sub: partnerExternalId }; + }, + deleteUser: jest.fn().mockRejectedValue(new Error('ADB2C Error')), + }); + + overrideSendgridService(service, { + createMailContentFromEmailConfirmForNormalUser: async () => { + return { html: '', text: '', subject: '' }; + }, + sendMail: async () => { + return; + }, + }); + overrideAccountsRepositoryService(service, { + createAccount: async () => { + throw new Error('DB Error'); + }, + }); + + overrideBlobstorageService(service, { + createContainer: async () => { + return; + }, + }); + + // DB上に用意されたデータが想定通りであるか確認 + { + const accounts = await getAccounts(source); + expect(accounts.length).toBe(1); + const users = await getUsers(source); + expect(users.length).toBe(1); + } + + try { + await service.createPartnerAccount( + context, + companyName, + country, + email, + adminName, + adminExternalId, + tier, + ); + } catch (e) { + if (e instanceof HttpException) { + expect(e.getStatus()).toBe(HttpStatus.INTERNAL_SERVER_ERROR); + expect(e.getResponse()).toEqual(makeErrorResponse('E009999')); + } else { + fail(); + } + } + + // DB上に作成されたデータが想定通りであるか確認 + { + const accounts = await getAccounts(source); + expect(accounts.length).toBe(1); + expect(accounts[0].tier).toBe(1); + const users = await getUsers(source); + expect(users.length).toBe(1); + expect(users[0].external_id).toBe(adminExternalId); + // ADB2Cユーザー削除メソッドが呼ばれているか確認 + expect(b2cService.deleteUser).toBeCalledWith(partnerExternalId, context); + } + }); + + it('BlobStorageへの通信失敗が原因でアカウントの追加に失敗した場合、リカバリ処理としてADB2C,DB上のデータが削除され、500エラーが返却される', async () => { + const module = await makeTestingModule(source); + const service = module.get(AccountsService); + const b2cService = module.get(AdB2cService); + + const parentExternalId = 'parent_external_id'; + + await createAccountAndAdminUser(source, parentExternalId); + + const context = makeContext(parentExternalId); + const partnerExternalId = 'partner_external_id'; + const companyName = 'partner_company_name'; + const country = 'US'; + const email = 'partner@example.com'; + const username = 'partner_username'; + + overrideAdB2cService(service, { + createUser: async () => { + return { sub: partnerExternalId }; + }, + deleteUser: jest.fn(), + }); + + overrideSendgridService(service, { + sendMail: async () => { + return; + }, + createMailContentFromEmailConfirmForNormalUser: async () => { + return { html: '', text: '', subject: '' }; + }, + }); + + overrideBlobstorageService(service, { + createContainer: async () => { + throw new Error(); + }, + }); + + // DB上に用意されたデータが想定通りであるか確認 + { + const accounts = await getAccounts(source); + expect(accounts.length).toBe(1); + } + + try { + await service.createPartnerAccount( + context, + companyName, + country, + email, + username, + parentExternalId, + TIERS.TIER1, + ); + } catch (e) { + if (e instanceof HttpException) { + expect(e.getStatus()).toBe(HttpStatus.INTERNAL_SERVER_ERROR); + expect(e.getResponse()).toEqual(makeErrorResponse('E009999')); + } else { + fail(); + } + } + + { + const accounts = await getAccounts(source); + expect(accounts.length).toBe(1); + expect(accounts[0].tier).toBe(1); + const users = await getUsers(source); + expect(users.length).toBe(1); + expect(users[0].external_id).toBe(parentExternalId); + // ADB2Cユーザー削除メソッドが呼ばれているか確認 + expect(b2cService.deleteUser).toBeCalledWith(partnerExternalId, context); + } + }); + + it('BlobStorageへの通信失敗が原因でアカウントの追加に失敗した場合、リカバリ処理が実行されるが、そのリカバリ処理に失敗した場合、500エラーが返却される', async () => { + const module = await makeTestingModule(source); + const service = module.get(AccountsService); + const b2cService = module.get(AdB2cService); + + const parentExternalId = 'parent_external_id'; + + await createAccountAndAdminUser(source, parentExternalId); + + const context = makeContext(parentExternalId); + const partnerExternalId = 'partner_external_id'; + const companyName = 'partner_company_name'; + const country = 'US'; + const email = 'partner@example.com'; + const username = 'partner_username'; + + overrideAdB2cService(service, { + createUser: async () => { + return { sub: partnerExternalId }; + }, + deleteUser: jest.fn().mockRejectedValue(new Error('ADB2C Error')), + }); + + overrideSendgridService(service, { + sendMail: async () => { + return; + }, + createMailContentFromEmailConfirmForNormalUser: async () => { + return { html: '', text: '', subject: '' }; + }, + }); + + overrideAccountsRepositoryService(service, { + deleteAccount: jest.fn().mockRejectedValue(new Error('DB Error')), + }); + + overrideBlobstorageService(service, { + createContainer: async () => { + throw new Error(); + }, + }); + + // DB上に用意されたデータが想定通りであるか確認 + { + const accounts = await getAccounts(source); + expect(accounts.length).toBe(1); + } + + try { + await service.createPartnerAccount( + context, + companyName, + country, + email, + username, + parentExternalId, + TIERS.TIER1, + ); + } catch (e) { + if (e instanceof HttpException) { + expect(e.getStatus()).toBe(HttpStatus.INTERNAL_SERVER_ERROR); + expect(e.getResponse()).toEqual(makeErrorResponse('E009999')); + } else { + fail(); + } + } + + { + // DB上に作成されたデータが想定通りであるか確認 + // リカバリ処理が失敗した場合、DB上のデータは削除されない + const accounts = await getAccounts(source); + expect(accounts.length).toBe(2); + expect(accounts[0].tier).toBe(1); + expect(accounts[1].tier).toBe(2); + const users = await getUsers(source); + expect(users.length).toBe(2); + expect(users[0].external_id).toBe(parentExternalId); + expect(users[1].external_id).toBe(partnerExternalId); + // ADB2Cユーザー削除メソッドが呼ばれているか確認 + expect(b2cService.deleteUser).toBeCalledWith(partnerExternalId, context); + } + }); + + it('SendGridへの通信失敗によって500エラーが発生した場合、リカバリ処理としてADB2C,DB上のデータ,コンテナが削除され、500エラーが返却される', async () => { + const module = await makeTestingModule(source); + const service = module.get(AccountsService); + const b2cService = module.get(AdB2cService); + const blobstorageService = + module.get(BlobstorageService); + + const parentExternalId = 'parent_external_id'; + + await createAccountAndAdminUser(source, parentExternalId); + + const context = makeContext(parentExternalId); + const partnerExternalId = 'partner_external_id'; + const companyName = 'partner_company_name'; + const country = 'US'; + const email = 'partner@example.com'; + const username = 'partner_username'; + + overrideAdB2cService(service, { + createUser: async () => { + return { sub: partnerExternalId }; + }, + deleteUser: jest.fn(), + }); + + overrideSendgridService(service, { + sendMail: async () => { + throw new Error(); + }, + createMailContentFromEmailConfirmForNormalUser: async () => { + return { html: '', text: '', subject: '' }; + }, + }); + + overrideBlobstorageService(service, { + createContainer: async () => { + return; + }, + deleteContainer: jest.fn(), + }); + + // DB上に用意されたデータが想定通りであるか確認 + { + const accounts = await getAccounts(source); + expect(accounts.length).toBe(1); + } + + try { + await service.createPartnerAccount( + context, + companyName, + country, + email, + username, + parentExternalId, + TIERS.TIER1, + ); + } catch (e) { + if (e instanceof HttpException) { + expect(e.getStatus()).toBe(HttpStatus.INTERNAL_SERVER_ERROR); + expect(e.getResponse()).toEqual(makeErrorResponse('E009999')); + } else { + fail(); + } + } + + { + // DB上に作成されたデータが想定通りであるか確認 + const accounts = await getAccounts(source); + expect(accounts.length).toBe(1); + expect(accounts[0].tier).toBe(1); + const users = await getUsers(source); + expect(users.length).toBe(1); + expect(users[0].external_id).toBe(parentExternalId); + // ADB2Cユーザー削除メソッドが呼ばれているか確認 + expect(b2cService.deleteUser).toBeCalledWith(partnerExternalId, context); + // コンテナ削除メソッドが呼ばれているか確認 + expect(blobstorageService.deleteContainer).toBeCalledWith( + context, + 2, //新規作成したパートナーのアカウントID + country, + ); + } + }); + + it('SendGridへの通信失敗によって500エラーが発生した場合、リカバリ処理が実行されるが、そのリカバリ処理に失敗した場合、500エラーが返却される', async () => { + const module = await makeTestingModule(source); + const service = module.get(AccountsService); + const b2cService = module.get(AdB2cService); + const blobstorageService = + module.get(BlobstorageService); + + const parentExternalId = 'parent_external_id'; + + await createAccountAndAdminUser(source, parentExternalId); + + const context = makeContext(parentExternalId); + const partnerExternalId = 'partner_external_id'; + const companyName = 'partner_company_name'; + const country = 'US'; + const email = 'partner@example.com'; + const username = 'partner_username'; + + overrideAdB2cService(service, { + createUser: async () => { + return { sub: partnerExternalId }; + }, + deleteUser: jest.fn().mockRejectedValue(new Error('ADB2C Error')), + }); + + overrideSendgridService(service, { + sendMail: async () => { + throw new Error(); + }, + createMailContentFromEmailConfirmForNormalUser: async () => { + return { html: '', text: '', subject: '' }; + }, + }); + + overrideAccountsRepositoryService(service, { + deleteAccount: jest.fn().mockRejectedValue(new Error('DB Error')), + }); + + overrideBlobstorageService(service, { + createContainer: async () => { + return; + }, + deleteContainer: jest.fn().mockRejectedValue(new Error('Blob Error')), + }); + + // DB上に用意されたデータが想定通りであるか確認 + { + const accounts = await getAccounts(source); + expect(accounts.length).toBe(1); + } + + try { + await service.createPartnerAccount( + context, + companyName, + country, + email, + username, + parentExternalId, + TIERS.TIER1, + ); + } catch (e) { + if (e instanceof HttpException) { + expect(e.getStatus()).toBe(HttpStatus.INTERNAL_SERVER_ERROR); + expect(e.getResponse()).toEqual(makeErrorResponse('E009999')); + } else { + fail(); + } + } + + { + // DB上に作成されたデータが想定通りであるか確認 + // リカバリ処理が失敗したため、DB上のデータは削除されていない + const accounts = await getAccounts(source); + expect(accounts.length).toBe(2); + expect(accounts[0].tier).toBe(1); + expect(accounts[1].tier).toBe(2); + const users = await getUsers(source); + expect(users.length).toBe(2); + expect(users[0].external_id).toBe(parentExternalId); + expect(users[1].external_id).toBe(partnerExternalId); + // ADB2Cユーザー削除メソッドが呼ばれているか確認 + expect(b2cService.deleteUser).toBeCalledWith(partnerExternalId, context); + // コンテナ削除メソッドが呼ばれているか確認 + expect(blobstorageService.deleteContainer).toBeCalledWith( + context, + 2, //新規作成したパートナーのアカウントID + country, + ); + } + }); + + it('既に登録済みのメールアドレスが原因でアカウントの追加に失敗した場合、エラーとなる(400エラー)', async () => { + const module = await makeTestingModule(source); + const service = module.get(AccountsService); + const adminExternalId = 'ADMIN0001'; + + // 第一階層のアカウントを作成 + const { tier } = await createAccountAndAdminUser(source, adminExternalId); + + const context = makeContext('uuid'); + const companyName = 'test_company_name'; + const country = 'US'; + const email = 'partner@example.com'; + const adminName = 'partner_admin'; + + overrideAdB2cService(service, { + createUser: async () => { + // Conflictエラーを返す + return { reason: 'email', message: 'dummy' }; + }, + }); + + overrideSendgridService(service, { + createMailContentFromEmailConfirmForNormalUser: async () => { + return { html: '', text: '', subject: '' }; + }, + sendMail: async () => { + return; + }, + }); + + overrideBlobstorageService(service, { + createContainer: async () => { + return; + }, + }); + + // DB上に用意されたデータが想定通りであるか確認 + { + const accounts = await getAccounts(source); + expect(accounts.length).toBe(1); + const users = await getUsers(source); + expect(users.length).toBe(1); + } + + try { + await service.createPartnerAccount( + context, + companyName, + country, + email, + adminName, + adminExternalId, + tier, + ); + } catch (e) { + if (e instanceof HttpException) { + expect(e.getStatus()).toBe(HttpStatus.BAD_REQUEST); + expect(e.getResponse()).toEqual(makeErrorResponse('E010301')); + } else { + fail(); + } + } + + // DB上に作成されたデータが想定通りであるか確認 + { + const accounts = await getAccounts(source); + expect(accounts.length).toBe(1); + const users = await getUsers(source); + expect(users.length).toBe(1); + } + }); +}); describe('AccountsService', () => { it('アカウントに紐づくライセンス情報を取得する', async () => { @@ -31,6 +1435,7 @@ describe('AccountsService', () => { makeDefaultAccountsRepositoryMockValue(); const configMockValue = makeDefaultConfigValue(); const sendGridMockValue = makeDefaultSendGridlValue(); + const blobStorageMockValue = makeBlobStorageServiceMockValue(); const licensesRepositoryMockValue = makeDefaultLicensesRepositoryMockValue(); const service = await makeAccountsServiceMock( @@ -40,6 +1445,7 @@ describe('AccountsService', () => { adb2cParam, configMockValue, sendGridMockValue, + blobStorageMockValue, licensesRepositoryMockValue, ); expect(await service.getLicenseSummary(accountId)).toEqual( @@ -58,6 +1464,7 @@ describe('AccountsService', () => { accountsRepositoryMockValue.getLicenseSummaryInfo = null; const configMockValue = makeDefaultConfigValue(); const sendGridMockValue = makeDefaultSendGridlValue(); + const blobStorageMockValue = makeBlobStorageServiceMockValue(); const licensesRepositoryMockValue = makeDefaultLicensesRepositoryMockValue(); const service = await makeAccountsServiceMock( @@ -67,6 +1474,7 @@ describe('AccountsService', () => { adb2cParam, configMockValue, sendGridMockValue, + blobStorageMockValue, licensesRepositoryMockValue, ); await expect(service.getLicenseSummary(accountId)).rejects.toEqual( @@ -87,6 +1495,7 @@ describe('AccountsService', () => { makeDefaultAccountsRepositoryMockValue(); const configMockValue = makeDefaultConfigValue(); const sendGridMockValue = makeDefaultSendGridlValue(); + const blobStorageMockValue = makeBlobStorageServiceMockValue(); const licensesRepositoryMockValue = makeDefaultLicensesRepositoryMockValue(); const service = await makeAccountsServiceMock( @@ -96,6 +1505,7 @@ describe('AccountsService', () => { adb2cParam, configMockValue, sendGridMockValue, + blobStorageMockValue, licensesRepositoryMockValue, ); expect(await service.getTypists(externalId)).toEqual([ @@ -115,6 +1525,7 @@ describe('AccountsService', () => { makeDefaultAccountsRepositoryMockValue(); const configMockValue = makeDefaultConfigValue(); const sendGridMockValue = makeDefaultSendGridlValue(); + const blobStorageMockValue = makeBlobStorageServiceMockValue(); const licensesRepositoryMockValue = makeDefaultLicensesRepositoryMockValue(); const service = await makeAccountsServiceMock( @@ -124,6 +1535,7 @@ describe('AccountsService', () => { adb2cParam, configMockValue, sendGridMockValue, + blobStorageMockValue, licensesRepositoryMockValue, ); await expect(service.getTypists(externalId)).rejects.toEqual( @@ -144,6 +1556,7 @@ describe('AccountsService', () => { makeDefaultAccountsRepositoryMockValue(); const configMockValue = makeDefaultConfigValue(); const sendGridMockValue = makeDefaultSendGridlValue(); + const blobStorageMockValue = makeBlobStorageServiceMockValue(); const licensesRepositoryMockValue = makeDefaultLicensesRepositoryMockValue(); const service = await makeAccountsServiceMock( @@ -153,6 +1566,7 @@ describe('AccountsService', () => { adb2cParam, configMockValue, sendGridMockValue, + blobStorageMockValue, licensesRepositoryMockValue, ); await expect(service.getTypists(externalId)).rejects.toEqual( @@ -173,6 +1587,7 @@ describe('AccountsService', () => { makeDefaultUserGroupsRepositoryMockValue(); const configMockValue = makeDefaultConfigValue(); const sendGridMockValue = makeDefaultSendGridlValue(); + const blobStorageMockValue = makeBlobStorageServiceMockValue(); const licensesRepositoryMockValue = makeDefaultLicensesRepositoryMockValue(); const service = await makeAccountsServiceMock( @@ -182,6 +1597,7 @@ describe('AccountsService', () => { adb2cParam, configMockValue, sendGridMockValue, + blobStorageMockValue, licensesRepositoryMockValue, ); @@ -201,6 +1617,7 @@ describe('AccountsService', () => { makeDefaultUserGroupsRepositoryMockValue(); const configMockValue = makeDefaultConfigValue(); const sendGridMockValue = makeDefaultSendGridlValue(); + const blobStorageMockValue = makeBlobStorageServiceMockValue(); const licensesRepositoryMockValue = makeDefaultLicensesRepositoryMockValue(); const service = await makeAccountsServiceMock( @@ -210,6 +1627,7 @@ describe('AccountsService', () => { adb2cParam, configMockValue, sendGridMockValue, + blobStorageMockValue, licensesRepositoryMockValue, ); @@ -231,6 +1649,7 @@ describe('AccountsService', () => { userGroupsRepositoryMockValue.getUserGroups = new Error('DB failed'); const configMockValue = makeDefaultConfigValue(); const sendGridMockValue = makeDefaultSendGridlValue(); + const blobStorageMockValue = makeBlobStorageServiceMockValue(); const licensesRepositoryMockValue = makeDefaultLicensesRepositoryMockValue(); const service = await makeAccountsServiceMock( @@ -240,6 +1659,7 @@ describe('AccountsService', () => { adb2cParam, configMockValue, sendGridMockValue, + blobStorageMockValue, licensesRepositoryMockValue, ); @@ -250,86 +1670,6 @@ describe('AccountsService', () => { ), ); }); - it('パートナーを追加できる', async () => { - const companyName = 'TEST_COMPANY'; - const country = 'US'; - const email = 'xxx@example.com'; - const adminName = 'ADMIN'; - const userId = '100'; - const tier = 3; - const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue(); - const userGroupsRepositoryMockValue = - makeDefaultUserGroupsRepositoryMockValue(); - const adb2cParam = makeDefaultAdB2cMockValue(); - const accountsRepositoryMockValue = - makeDefaultAccountsRepositoryMockValue(); - const configMockValue = makeDefaultConfigValue(); - const sendGridMockValue = makeDefaultSendGridlValue(); - const licensesRepositoryMockValue = - makeDefaultLicensesRepositoryMockValue(); - const service = await makeAccountsServiceMock( - accountsRepositoryMockValue, - usersRepositoryMockValue, - userGroupsRepositoryMockValue, - adb2cParam, - configMockValue, - sendGridMockValue, - licensesRepositoryMockValue, - ); - expect( - await service.createPartnerAccount( - companyName, - country, - email, - adminName, - userId, - tier + 1, - ), - ).toEqual(undefined); - }); - it('アカウントの追加に失敗した場合、エラーとなる', async () => { - const companyName = 'TEST_COMPANY'; - const country = 'US'; - const email = 'xxx@example.com'; - const adminName = 'ADMIN'; - const userId = '100'; - const tier = 3; - const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue(); - const userGroupsRepositoryMockValue = - makeDefaultUserGroupsRepositoryMockValue(); - const adb2cParam = makeDefaultAdB2cMockValue(); - const accountsRepositoryMockValue = - makeDefaultAccountsRepositoryMockValue(); - accountsRepositoryMockValue.createAccount = new Error('DB failed'); - const configMockValue = makeDefaultConfigValue(); - const sendGridMockValue = makeDefaultSendGridlValue(); - const licensesRepositoryMockValue = - makeDefaultLicensesRepositoryMockValue(); - const service = await makeAccountsServiceMock( - accountsRepositoryMockValue, - usersRepositoryMockValue, - userGroupsRepositoryMockValue, - adb2cParam, - configMockValue, - sendGridMockValue, - licensesRepositoryMockValue, - ); - await expect( - service.createPartnerAccount( - companyName, - country, - email, - adminName, - userId, - tier + 1, - ), - ).rejects.toEqual( - new HttpException( - makeErrorResponse('E009999'), - HttpStatus.INTERNAL_SERVER_ERROR, - ), - ); - }); }); const expectedAccountLisenceCounts = { @@ -346,7 +1686,7 @@ const expectedAccountLisenceCounts = { isStorageAvailable: false, }; -describe('createPartnerAccount', () => { +describe('getPartnerAccount', () => { let source: DataSource = null; beforeEach(async () => { source = new DataSource({ @@ -387,6 +1727,20 @@ describe('createPartnerAccount', () => { 'CHILDCORP2', ); + // 第二にリクエストを投げる用の第三を作成 + const { accountId: childAccountId3 } = await createAccount( + source, + childAccountId1, + 3, + 'CHILDCORP3', + ); + const { accountId: childAccountId4 } = await createAccount( + source, + childAccountId2, + 3, + 'CHILDCORP4', + ); + // 所有ライセンスを追加(親:3、子1:1、子2:2) await createLicense(source, parentAccountId); await createLicense(source, parentAccountId); @@ -407,6 +1761,10 @@ describe('createPartnerAccount', () => { ); await createLicenseOrder(source, childAccountId2, parentAccountId, 5); + // ライセンス注文を追加(子3→子1:10ライセンス、子4→子2:10ライセンス) + await createLicenseOrder(source, childAccountId3, childAccountId1, 10); + await createLicenseOrder(source, childAccountId4, childAccountId2, 10); + const service = module.get(AccountsService); const accountId = parentAccountId; const offset = 0; @@ -426,11 +1784,135 @@ describe('createPartnerAccount', () => { 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].issueRequesting).toBe(5); + expect(response.childrenPartnerLicenses[1].shortage).toBe(8); + }); +}); + +describe('getPartnerAccount', () => { + let source: DataSource = null; + beforeEach(async () => { + source = new DataSource({ + type: 'sqlite', + database: ':memory:', + logging: false, + entities: [__dirname + '/../../**/*.entity{.ts,.js}'], + synchronize: true, // trueにすると自動的にmigrationが行われるため注意 + }); + return source.initialize(); + }); + + afterEach(async () => { + await source.destroy(); + source = null; + }); + + it('パラメータのアカウント自身と子アカウントに紐つくライセンス情報を取得する(第五のshortage確認)', async () => { + const module = await makeTestingModule(source); + + // 親アカウントと子アカウント2つ作成 + const { accountId: parentAccountId } = await createAccount( + source, + 0, + 4, + 'PARENTCORP', + ); + const { accountId: childAccountId1 } = await createAccount( + source, + parentAccountId, + 5, + 'CHILDCORP1', + ); + const { accountId: childAccountId2 } = await createAccount( + source, + parentAccountId, + 5, + 'CHILDCORP2', + ); + const { accountId: childAccountId3 } = await createAccount( + source, + parentAccountId, + 5, + 'CHILDCORP3', + ); + + // 有効期限が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', + ); + await createLicenseSetExpiryDateAndStatus( + source, + childAccountId2, + expiryDate, + 'Allocated', + ); + } + + // 有効期限が15日後のライセンスを追加 + expiryDate.setDate(expiryDate.getDate() + 15); + expiryDate.setHours(23, 59, 59, 999); + await createLicenseSetExpiryDateAndStatus( + source, + childAccountId3, + expiryDate, + 'Allocated', + ); + + // 有効期限が迫っていないライセンスを追加(子1:各ステータスのライセンスを1つずつ、計4つ) + const status = ['Unallocated', 'Allocated', 'Reusable', 'Deleted']; + status.forEach(async (element) => { + await createLicenseSetExpiryDateAndStatus( + source, + childAccountId1, + new Date(2500, 1, 1, 23, 59, 59), + element, + ); + }); + + // 有効期限が迫っていないライセンスを追加(子2:Unallocatedを10件) + for (let i = 0; i < 10; i++) { + await createLicenseSetExpiryDateAndStatus( + source, + childAccountId2, + new Date(2500, 1, 1, 23, 59, 59), + 'Unallocated', + ); + } + + // 有効期限未設定のライセンスを1件追加(子1) + await createLicense(source, childAccountId1); + + const service = module.get(AccountsService); + const accountId = parentAccountId; + const offset = 0; + const limit = 20; + + const response = await service.getPartnerLicenses(limit, offset, accountId); + + // 有効期限間近(5件)+ 有効期限間近でない(3件)'Unallocated', 'Allocated', 'Reusable'+ 有効期限未設定(1件) → 9件 + expect(response.childrenPartnerLicenses[0].stockLicense).toBe(9); + // 有効期限間近(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件)'Unallocated' + 有効期限未設定(1件)) → -5件 → 0件 + expect(response.childrenPartnerLicenses[1].shortage).toBe(0); + + expect(response.childrenPartnerLicenses[2].stockLicense).toBe(1); + // 有効期限が15日後のものはshortageにカウントされない + expect(response.childrenPartnerLicenses[2].shortage).toBe(0); }); }); @@ -526,6 +2008,7 @@ describe('getOrderHistories', () => { makeDefaultAccountsRepositoryMockValue(); const configMockValue = makeDefaultConfigValue(); const sendGridMockValue = makeDefaultSendGridlValue(); + const blobStorageMockValue = makeBlobStorageServiceMockValue(); const licensesRepositoryMockValue = makeDefaultLicensesRepositoryMockValue(); licensesRepositoryMockValue.getLicenseOrderHistoryInfo = new Error( @@ -538,6 +2021,7 @@ describe('getOrderHistories', () => { adb2cParam, configMockValue, sendGridMockValue, + blobStorageMockValue, licensesRepositoryMockValue, ); await expect( @@ -551,6 +2035,190 @@ describe('getOrderHistories', () => { }); }); +describe('issueLicense', () => { + let source: DataSource = null; + beforeEach(async () => { + source = new DataSource({ + type: 'sqlite', + database: ':memory:', + logging: false, + entities: [__dirname + '/../../**/*.entity{.ts,.js}'], + synchronize: true, // trueにすると自動的にmigrationが行われるため注意 + }); + return source.initialize(); + }); + + afterEach(async () => { + await source.destroy(); + source = null; + }); + + it('指定した注文を発行済みにする', async () => { + const module = await makeTestingModule(source); + const service = module.get(AccountsService); + const now = new Date(); + // 親と子アカウントを作成する + const { accountId: parentAccountId } = await createAccount( + source, + 0, + 2, + 'PARENTCORP', + ); + const { accountId: childAccountId } = await createAccount( + source, + parentAccountId, + 3, + 'CHILDCORP1', + ); + // 親と子のユーザーを作成する + const { externalId } = await createUser( + source, + parentAccountId, + 'userId-parent', + 'admin', + ); + + // 親のライセンスを作成する(3個) + await createLicense(source, parentAccountId); + await createLicense(source, parentAccountId); + await createLicense(source, parentAccountId); + // 子から親への注文を作成する(2個) + await createLicenseOrder( + source, + childAccountId, + parentAccountId, + 2, + 'TEST001', + new Date(now.getTime() + 60 * 60 * 1000), + ); + + const context = makeContext('userId-parent'); + + // 注文を発行済みにする + await service.issueLicense( + context, + childAccountId, + externalId, + 2, + 'TEST001', + ); + + const issuedLicenses = await source.getRepository(License).find({ + where: { + account_id: childAccountId, + status: 'Unallocated', + type: 'NORMAL', + }, + }); + expect(issuedLicenses.length).toEqual(2); + }); + it('既に注文が発行済みの場合、エラーとなる', async () => { + const module = await makeTestingModule(source); + const service = module.get(AccountsService); + const now = new Date(); + // 親と子アカウントを作成する + const { accountId: parentAccountId } = await createAccount( + source, + 0, + 2, + 'PARENTCORP', + ); + const { accountId: childAccountId } = await createAccount( + source, + parentAccountId, + 3, + 'CHILDCORP1', + ); + // 親と子のユーザーを作成する + const { externalId } = await createUser( + source, + parentAccountId, + 'userId-parent', + 'admin', + ); + + // 親のライセンスを作成する(3個) + await createLicense(source, parentAccountId); + await createLicense(source, parentAccountId); + await createLicense(source, parentAccountId); + // 子から親への注文を作成する(2個) + await createLicenseOrder( + source, + childAccountId, + parentAccountId, + 2, + 'TEST001', + new Date(now.getTime() + 60 * 60 * 1000), + ); + + const context = makeContext('userId-parent'); + + // 注文を発行済みにする + await service.issueLicense( + context, + childAccountId, + externalId, + 2, + 'TEST001', + ); + + //再度同じ処理を行う + await expect( + service.issueLicense(context, childAccountId, externalId, 2, 'TEST001'), + ).rejects.toEqual( + new HttpException(makeErrorResponse('E010803'), HttpStatus.BAD_REQUEST), + ); + }); + it('ライセンスが不足している場合、エラーとなる', async () => { + const module = await makeTestingModule(source); + const service = module.get(AccountsService); + const now = new Date(); + // 親と子アカウントを作成する + const { accountId: parentAccountId } = await createAccount( + source, + 0, + 2, + 'PARENTCORP', + ); + const { accountId: childAccountId } = await createAccount( + source, + parentAccountId, + 3, + 'CHILDCORP1', + ); + // 親と子のユーザーを作成する + const { externalId } = await createUser( + source, + parentAccountId, + 'userId-parent', + 'admin', + ); + + // 親のライセンスを作成する(3個) + await createLicense(source, parentAccountId); + await createLicense(source, parentAccountId); + await createLicense(source, parentAccountId); + // 子から親への注文を作成する(4個) + await createLicenseOrder( + source, + childAccountId, + parentAccountId, + 4, + 'TEST001', + new Date(now.getTime() + 60 * 60 * 1000), + ); + + const context = makeContext('userId-parent'); + + // 注文を発行済みにする + await expect( + service.issueLicense(context, childAccountId, externalId, 2, 'TEST001'), + ).rejects.toEqual( + new HttpException(makeErrorResponse('E010804'), HttpStatus.BAD_REQUEST), + ); + }); +}); + describe('getDealers', () => { let source: DataSource = null; beforeEach(async () => { @@ -568,7 +2236,6 @@ describe('getDealers', () => { await source.destroy(); source = null; }); - it('Dealerを取得できる', async () => { const module = await makeTestingModule(source); const { accountId: accountId_1 } = await createAccount( diff --git a/dictation_server/src/features/accounts/accounts.service.ts b/dictation_server/src/features/accounts/accounts.service.ts index 9995b94..7c1cc7b 100644 --- a/dictation_server/src/features/accounts/accounts.service.ts +++ b/dictation_server/src/features/accounts/accounts.service.ts @@ -10,11 +10,7 @@ import { } from '../../gateways/adb2c/adb2c.service'; import { Account } from '../../repositories/accounts/entity/account.entity'; import { User } from '../../repositories/users/entity/user.entity'; -import { - LICENSE_EXPIRATION_THRESHOLD_DAYS, - TIERS, - USER_ROLES, -} from '../../constants'; +import { TIERS, USER_ROLES } from '../../constants'; import { makeErrorResponse } from '../../common/error/makeErrorResponse'; import { TypistGroup, @@ -26,7 +22,10 @@ import { Dealer, GetMyAccountResponse, } from './types/types'; -import { DateWithZeroTime } from '../licenses/types/types'; +import { + DateWithZeroTime, + ExpirationThresholdDate, +} from '../licenses/types/types'; import { GetLicenseSummaryResponse, Typist } from './types/types'; import { AccessToken } from '../../common/token'; import { UserNotFoundError } from '../../repositories/users/errors/types'; @@ -34,6 +33,14 @@ import { UserGroupsRepositoryService } from '../../repositories/user_groups/user import { makePassword } from '../../common/password'; import { LicensesRepositoryService } from '../../repositories/licenses/licenses.repository.service'; import { AccountNotFoundError } from '../../repositories/accounts/errors/types'; +import { Context } from '../../common/log'; +import { + LicensesShortageError, + AlreadyIssuedError, + OrderNotFoundError, +} from '../../repositories/licenses/errors/types'; +import { BlobstorageService } from '../../gateways/blobstorage/blobstorage.service'; + @Injectable() export class AccountsService { constructor( @@ -43,6 +50,7 @@ export class AccountsService { private readonly userGroupsRepository: UserGroupsRepositoryService, private readonly adB2cService: AdB2cService, private readonly sendgridService: SendGridService, + private readonly blobStorageService: BlobstorageService, private readonly configService: ConfigService, ) {} private readonly logger = new Logger(AccountsService.name); @@ -58,13 +66,9 @@ export class AccountsService { try { const currentDate = new DateWithZeroTime(); - - const expiringSoonDate = new Date(currentDate.getTime()); - expiringSoonDate.setDate( - currentDate.getDate() + LICENSE_EXPIRATION_THRESHOLD_DAYS, + const expiringSoonDate = new ExpirationThresholdDate( + currentDate.getTime(), ); - // システム上有効期限日付の23時59分59秒999ミリ秒までライセンスは有効なため、各値最大値をセット - expiringSoonDate.setHours(23, 59, 59, 999); const { licenseSummary, isStorageAvailable } = await this.accountRepository.getLicenseSummaryInfo( @@ -118,100 +122,221 @@ export class AccountsService { * @returns account */ async createAccount( + context: Context, companyName: string, country: string, - dealerAccountId: number | null, + dealerAccountId: number | undefined, email: string, password: string, username: string, role: string, acceptedTermsVersion: string, ): Promise<{ accountId: number; userId: number; externalUserId: string }> { - let externalUser: { sub: string } | ConflictError; + this.logger.log( + `[IN] [${context.trackingId}] ${this.createAccount.name} | params: { ` + + `country: ${country}, ` + + `dealerAccountId: ${dealerAccountId}, ` + + `role: ${role}, ` + + `acceptedTermsVersion: ${acceptedTermsVersion} };`, + ); try { - // idpにユーザーを作成 - externalUser = await this.adB2cService.createUser( - email, - password, - username, - ); - } catch (e) { - console.log(e); - console.log('create externalUser failed'); - - throw new HttpException( - makeErrorResponse('E009999'), - HttpStatus.INTERNAL_SERVER_ERROR, - ); - } - - // メールアドレス重複エラー - if (isConflictError(externalUser)) { - throw new HttpException( - makeErrorResponse('E010301'), - HttpStatus.BAD_REQUEST, - ); - } - - let account: Account; - let user: User; - try { - // アカウントと管理者をセットで作成 - const { newAccount, adminUser } = - await this.accountRepository.createAccount( - companyName, - country, - dealerAccountId, - TIERS.TIER5, - externalUser.sub, - role, - acceptedTermsVersion, - ); - account = newAccount; - user = adminUser; - } catch (e) { - console.log('create account failed'); - console.log( - `[NOT IMPLEMENT] [RECOVER] delete account: ${externalUser.sub}`, - ); - throw new HttpException( - makeErrorResponse('E009999'), - HttpStatus.INTERNAL_SERVER_ERROR, - ); - } - - try { - // メールの送信元を取得 - const from = this.configService.get('MAIL_FROM') ?? ''; - - // メールの内容を構成 - const { subject, text, html } = - await this.sendgridService.createMailContentFromEmailConfirm( - account.id, - user.id, + let externalUser: { sub: string } | ConflictError; + try { + // idpにユーザーを作成 + externalUser = await this.adB2cService.createUser( + context, email, + password, + username, ); + } catch (e) { + this.logger.error(`error=${e}`); + this.logger.error('create externalUser failed'); - // メールを送信 - await this.sendgridService.sendMail(email, from, subject, text, html); + throw new HttpException( + makeErrorResponse('E009999'), + HttpStatus.INTERNAL_SERVER_ERROR, + ); + } + + // メールアドレス重複エラー + if (isConflictError(externalUser)) { + this.logger.error(`email conflict. externalUser: ${externalUser}`); + throw new HttpException( + makeErrorResponse('E010301'), + HttpStatus.BAD_REQUEST, + ); + } + + let account: Account; + let user: User; + try { + // アカウントと管理者をセットで作成 + const { newAccount, adminUser } = + await this.accountRepository.createAccount( + companyName, + country, + dealerAccountId, + TIERS.TIER5, + externalUser.sub, + role, + acceptedTermsVersion, + ); + account = newAccount; + user = adminUser; + this.logger.log( + `[${context.trackingId}] adminUser.external_id: ${user.external_id}`, + ); + } catch (e) { + this.logger.error(`error=${e}`); + this.logger.error('create account failed'); + //リカバリ処理 + // idpのユーザーを削除 + await this.deleteAdB2cUser(externalUser.sub, context); + + throw new HttpException( + makeErrorResponse('E009999'), + HttpStatus.INTERNAL_SERVER_ERROR, + ); + } + + // 新規作成アカウント用のBlobコンテナを作成 + try { + await this.blobStorageService.createContainer( + context, + account.id, + country, + ); + } catch (e) { + this.logger.error(`error=${e}`); + this.logger.error('create container failed'); + //リカバリ処理 + // idpのユーザーを削除 + await this.deleteAdB2cUser(externalUser.sub, context); + + // DBのアカウントを削除 + await this.deleteAccount(account.id, user.id, context); + + throw new HttpException( + makeErrorResponse('E009999'), + HttpStatus.INTERNAL_SERVER_ERROR, + ); + } + + try { + // メールの送信元を取得 + const from = this.configService.get('MAIL_FROM') ?? ''; + + // メールの内容を構成 + const { subject, text, html } = + await this.sendgridService.createMailContentFromEmailConfirm( + context, + account.id, + user.id, + email, + ); + + // メールを送信 + await this.sendgridService.sendMail( + context, + email, + from, + subject, + text, + html, + ); + } catch (e) { + this.logger.error(`error=${e}`); + this.logger.error('send E-mail failed'); + //リカバリ処理 + // idpのユーザーを削除 + await this.deleteAdB2cUser(externalUser.sub, context); + + // DBのアカウントを削除 + await this.deleteAccount(account.id, user.id, context); + + // Blobコンテナを削除 + await this.deleteBlobContainer(account.id, country, context); + + throw new HttpException( + makeErrorResponse('E009999'), + HttpStatus.INTERNAL_SERVER_ERROR, + ); + } + + return { + accountId: account.id, + userId: user.id, + externalUserId: user.external_id, + }; } catch (e) { - console.log('create user failed'); - console.log(`[NOT IMPLEMENT] [RECOVER] delete account: ${account.id}`); - console.log( - `[NOT IMPLEMENT] [RECOVER] delete externalUser: ${externalUser.sub}`, - ); - console.log(`[NOT IMPLEMENT] [RECOVER] delete user: ${user.id}`); - throw new HttpException( - makeErrorResponse('E009999'), - HttpStatus.INTERNAL_SERVER_ERROR, + throw e; + } finally { + this.logger.log( + `[OUT] [${context.trackingId}] ${this.createAccount.name}`, ); } + } - return { - accountId: account.id, - userId: user.id, - externalUserId: user.external_id, - }; + // AdB2cのユーザーを削除 + // TODO「タスク 2452: リトライ処理を入れる箇所を検討し、実装する」の候補 + private async deleteAdB2cUser( + externalUserId: string, + context: Context, + ): Promise { + try { + await this.adB2cService.deleteUser(externalUserId, context); + this.logger.log( + `[${context.trackingId}] delete externalUser: ${externalUserId}`, + ); + } catch (error) { + this.logger.error(`error=${error}`); + this.logger.error( + `[MANUAL_RECOVERY_REQUIRED] [${context.trackingId}] Failed to delete externalUser: ${externalUserId}`, + ); + } + } + + // DBのアカウントを削除 + private async deleteAccount( + accountId: number, + userId: number, + context: Context, + ): Promise { + try { + await this.accountRepository.deleteAccount(accountId, userId); + this.logger.log( + `[${context.trackingId}] delete account: ${accountId}, user: ${userId}`, + ); + } catch (error) { + this.logger.error(`error=${error}`); + this.logger.error( + `[MANUAL_RECOVERY_REQUIRED] [${context.trackingId}] Failed to delete account: ${accountId}, user: ${userId}`, + ); + } + } + + // Blobコンテナを削除 + // TODO「タスク 2452: リトライ処理を入れる箇所を検討し、実装する」の候補 + private async deleteBlobContainer( + accountId: number, + country: string, + context: Context, + ): Promise { + try { + await this.blobStorageService.deleteContainer( + context, + accountId, + country, + ); + this.logger.log( + `[${context.trackingId}] delete container: ${accountId}, country: ${country}`, + ); + } catch (error) { + this.logger.error( + `[MANUAL_RECOVERY_REQUIRED] [${context.trackingId}] Failed to delete container: ${accountId}, country: ${country}`, + ); + } } /** @@ -335,97 +460,168 @@ export class AccountsService { /** * パートナーを追加する - * @param companyName - * @param country - * @param email - * @param adminName - * @param userId - * @param tier + * @param companyName パートナーの会社名 + * @param country パートナーの所属する国 + * @param email パートナーの管理者のメールアドレス + * @param adminName パートナーの管理者の名前 + * @param creatorUserId パートナーを作成する上位階層アカウントのユーザーID + * @param creatorAccountTier パートナーを作成する上位階層アカウントの階層 */ async createPartnerAccount( + context: Context, companyName: string, country: string, email: string, adminName: string, - userId: string, - tier: number, - ): Promise { - this.logger.log(`[IN] ${this.createPartnerAccount.name}`); - - let myAccountId: number; + creatorUserId: string, + creatorAccountTier: number, + ): Promise<{ accountId: number }> { + this.logger.log( + `[IN] [${context.trackingId}] ${this.createPartnerAccount.name} | params: { creatorUserId: ${creatorUserId}, creatorAccountTier: ${creatorAccountTier} };`, + ); try { - // アクセストークンからユーザーIDを取得する - myAccountId = (await this.usersRepository.findUserByExternalId(userId)) - .account_id; - } catch (e) { - this.logger.error(`error=${e}`); - if (e instanceof UserNotFoundError) { - throw new HttpException( - makeErrorResponse('E010204'), - HttpStatus.BAD_REQUEST, + let myAccountId: number; + + try { + // アクセストークンからユーザーIDを取得する + myAccountId = ( + await this.usersRepository.findUserByExternalId(creatorUserId) + ).account_id; + } catch (e) { + this.logger.error(`error=${e}`); + if (e instanceof UserNotFoundError) { + throw new HttpException( + makeErrorResponse('E010204'), + HttpStatus.BAD_REQUEST, + ); + } else { + throw new HttpException( + makeErrorResponse('E009999'), + HttpStatus.INTERNAL_SERVER_ERROR, + ); + } + } + + const ramdomPassword = makePassword(); + + let externalUser: { sub: string } | ConflictError; + + try { + // 管理者ユーザを作成し、AzureADB2C IDを取得する + externalUser = await this.adB2cService.createUser( + context, + email, + ramdomPassword, + adminName, ); - } else { + } catch (e) { + this.logger.error(`error=${e}`); throw new HttpException( makeErrorResponse('E009999'), HttpStatus.INTERNAL_SERVER_ERROR, ); } - } + // メールアドレスが重複していた場合はエラーを返す + if (isConflictError(externalUser)) { + throw new HttpException( + makeErrorResponse('E010301'), + HttpStatus.BAD_REQUEST, + ); + } - const ramdomPassword = makePassword(); + let account: Account; + let user: User; + try { + // アカウントと管理者をセットで作成 + const { newAccount, adminUser } = + await this.accountRepository.createAccount( + companyName, + country, + myAccountId, + creatorAccountTier + 1, + externalUser.sub, + USER_ROLES.NONE, + null, + ); + account = newAccount; + user = adminUser; + } catch (e) { + this.logger.error(`error=${e}`); + this.logger.error('create partner account failed'); + //リカバリ処理 + // idpのユーザーを削除 + await this.deleteAdB2cUser(externalUser.sub, context); - let externalUser: { sub: string } | ConflictError; + throw new HttpException( + makeErrorResponse('E009999'), + HttpStatus.INTERNAL_SERVER_ERROR, + ); + } - try { - // 管理者ユーザを作成し、AzureADB2C IDを取得する - externalUser = await this.adB2cService.createUser( - email, - ramdomPassword, - adminName, - ); - } catch (e) { - this.logger.error(`error=${e}`); - throw new HttpException( - makeErrorResponse('E009999'), - HttpStatus.INTERNAL_SERVER_ERROR, - ); - } - // メールアドレスが重複していた場合はエラーを返す - if (isConflictError(externalUser)) { - throw new HttpException( - makeErrorResponse('E010301'), - HttpStatus.BAD_REQUEST, - ); - } - - try { - // アカウントと管理者をセットで作成 - const { newAccount, adminUser } = - await this.accountRepository.createAccount( - companyName, + try { + // 新規作成アカウント用のBlobコンテナを作成 + await this.blobStorageService.createContainer( + context, + account.id, country, - myAccountId, - tier + 1, - externalUser.sub, - USER_ROLES.NONE, - null, ); + } catch (e) { + this.logger.error(`error=${e}`); + this.logger.error('create partner container failed'); + //リカバリ処理 + // idpのユーザーを削除 + await this.deleteAdB2cUser(externalUser.sub, context); - const from = this.configService.get('MAIL_FROM') || ''; - const { subject, text, html } = - await this.sendgridService.createMailContentFromEmailConfirmForNormalUser( - newAccount.id, - adminUser.id, - email, + // DBのアカウントとユーザーを削除 + await this.deleteAccount(account.id, user.id, context); + + throw new HttpException( + makeErrorResponse('E009999'), + HttpStatus.INTERNAL_SERVER_ERROR, ); - await this.sendgridService.sendMail(email, from, subject, text, html); + } + + try { + const from = this.configService.get('MAIL_FROM') || ''; + const { subject, text, html } = + await this.sendgridService.createMailContentFromEmailConfirmForNormalUser( + account.id, + user.id, + email, + ); + await this.sendgridService.sendMail( + context, + email, + from, + subject, + text, + html, + ); + return { accountId: account.id }; + } catch (e) { + this.logger.error(`error=${e}`); + this.logger.error('create partner account send mail failed'); + //リカバリ処理 + // idpのユーザーを削除 + await this.deleteAdB2cUser(externalUser.sub, context); + + // DBのアカウントを削除 + await this.deleteAccount(account.id, user.id, context); + + // Blobコンテナを削除 + await this.deleteBlobContainer(account.id, country, context); + + throw new HttpException( + makeErrorResponse('E009999'), + HttpStatus.INTERNAL_SERVER_ERROR, + ); + } } catch (e) { - this.logger.error(`error=${e}`); - this.logger.error('create partner account failed'); - throw new HttpException( - makeErrorResponse('E009999'), - HttpStatus.INTERNAL_SERVER_ERROR, + throw e; + } finally { + this.logger.log( + `[OUT] [${context.trackingId}] ${this.createPartnerAccount.name}`, ); } } @@ -446,11 +642,17 @@ export class AccountsService { try { const currentDate = new DateWithZeroTime(); + // 第五階層のshortage算出に使用する日付情報 + // 「有効期限が現在日付からしきい値以内のライセンス数」を取得するため、しきい値となる日付を作成する + const expiringSoonDate = new ExpirationThresholdDate( + currentDate.getTime(), + ); const getPartnerLicenseResult = await this.accountRepository.getPartnerLicense( accountId, currentDate, + expiringSoonDate, offset, limit, ); @@ -471,27 +673,14 @@ export class AccountsService { }, ); - // 第五階層のshortage算出に使用する日付情報 - // 「有効期限が現在日付からしきい値以内のライセンス数」を取得するため、しきい値となる日付を作成する - const expiringSoonDate = new Date(currentDate.getTime()); - expiringSoonDate.setDate( - currentDate.getDate() + LICENSE_EXPIRATION_THRESHOLD_DAYS, - ); - expiringSoonDate.setHours(23, 59, 59, 999); - // 各子アカウントのShortageを算出してreturn用の変数にマージする const childrenPartnerLicenses: PartnerLicenseInfo[] = []; for (const childPartnerLicenseFromRepository of getPartnerLicenseResult.childPartnerLicensesFromRepository) { let childShortage; if (childPartnerLicenseFromRepository.tier === TIERS.TIER5) { - // 第五階層の場合計算式が異なるため、別途値を取得する - const { expiringSoonLicense, allocatableLicenseWithMargin } = - await this.accountRepository.getLicenseCountForShortage( - childPartnerLicenseFromRepository.accountId, - currentDate, - expiringSoonDate, - ); - childShortage = allocatableLicenseWithMargin - expiringSoonLicense; + childShortage = + childPartnerLicenseFromRepository.allocatableLicenseWithMargin - + childPartnerLicenseFromRepository.expiringSoonLicense; } else { childShortage = childPartnerLicenseFromRepository.stockLicense - @@ -587,6 +776,72 @@ export class AccountsService { } } + /** + * 対象の注文を発行する + * @param context + * @param orderedAccountId + * @param userId + * @param tier + * @param poNumber + */ + async issueLicense( + context: Context, + orderedAccountId: number, + userId: string, + tier: number, + poNumber: string, + ): Promise { + this.logger.log( + `[IN] [${context.trackingId}] ${this.issueLicense.name} | params: { ` + + `orderedAccountId: ${orderedAccountId}, ` + + `userId: ${userId}, ` + + `tier: ${tier}, ` + + `poNumber: ${poNumber} };`, + ); + try { + // アクセストークンからユーザーIDを取得する + const myAccountId = ( + await this.usersRepository.findUserByExternalId(userId) + ).account_id; + await this.licensesRepository.issueLicense( + orderedAccountId, + myAccountId, + tier, + poNumber, + ); + } catch (e) { + this.logger.error(`error=${e}`); + if (e instanceof Error) { + switch (e.constructor) { + case OrderNotFoundError: + throw new HttpException( + makeErrorResponse('E010801'), + HttpStatus.BAD_REQUEST, + ); + case AlreadyIssuedError: + throw new HttpException( + makeErrorResponse('E010803'), + HttpStatus.BAD_REQUEST, + ); + case LicensesShortageError: + throw new HttpException( + makeErrorResponse('E010804'), + HttpStatus.BAD_REQUEST, + ); + default: + throw new HttpException( + makeErrorResponse('E009999'), + HttpStatus.INTERNAL_SERVER_ERROR, + ); + } + } + } finally { + this.logger.log( + `[OUT] [${context.trackingId}] ${this.issueLicense.name}`, + ); + } + } + // dealersのアカウント情報を取得する async getDealers(): Promise { this.logger.log(`[IN] ${this.getDealers.name}`); 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 9f964c4..c18d259 100644 --- a/dictation_server/src/features/accounts/test/accounts.service.mock.ts +++ b/dictation_server/src/features/accounts/test/accounts.service.mock.ts @@ -14,6 +14,8 @@ import { UserGroup } from '../../../repositories/user_groups/entity/user_group.e import { UserGroupsRepositoryService } from '../../../repositories/user_groups/user_groups.repository.service'; import { AdB2cUser } from '../../../gateways/adb2c/types/types'; import { LicensesRepositoryService } from '../../../repositories/licenses/licenses.repository.service'; +import { Context } from '../../../common/log'; +import { BlobstorageService } from '../../../gateways/blobstorage/blobstorage.service'; export type LicensesRepositoryMockValue = { getLicenseOrderHistoryInfo: @@ -22,6 +24,7 @@ export type LicensesRepositoryMockValue = { orderHistories: LicenseOrder[]; } | Error; + issueLicense: undefined | Error; }; export type UsersRepositoryMockValue = { findUserById: User | Error; @@ -58,6 +61,15 @@ export type AccountsRepositoryMockValue = { }; createAccount: { newAccount: Account; adminUser: User } | Error; }; + +export type BlobStorageServiceMockValue = { + createContainer: void | Error; + containerExists: boolean | Error; + fileExists: boolean | Error; + publishUploadSas: string | Error; + publishDownloadSas: string | Error; +}; + export const makeAccountsServiceMock = async ( accountsRepositoryMockValue: AccountsRepositoryMockValue, usersRepositoryMockValue: UsersRepositoryMockValue, @@ -65,6 +77,7 @@ export const makeAccountsServiceMock = async ( adB2cMockValue: AdB2cMockValue, configMockValue: ConfigMockValue, sendGridMockValue: SendGridMockValue, + blobStorageMockValue: BlobStorageServiceMockValue, licensesRepositoryMockValue: LicensesRepositoryMockValue, ): Promise => { const module: TestingModule = await Test.createTestingModule({ @@ -90,6 +103,8 @@ export const makeAccountsServiceMock = async ( return makeConfigMock(configMockValue); case SendGridService: return makeSendGridServiceMock(sendGridMockValue); + case BlobstorageService: + return makeBlobStorageServiceMock(blobStorageMockValue); case LicensesRepositoryService: return makeLicensesRepositoryMock(licensesRepositoryMockValue); } @@ -127,10 +142,10 @@ export const makeAccountsRepositoryMock = ( export const makeLicensesRepositoryMock = ( value: LicensesRepositoryMockValue, ) => { - const { getLicenseOrderHistoryInfo } = value; + const { getLicenseOrderHistoryInfo, issueLicense } = value; return { - findUserById: + getLicenseOrderHistoryInfo: getLicenseOrderHistoryInfo instanceof Error ? jest .fn, []>() @@ -141,6 +156,21 @@ export const makeLicensesRepositoryMock = ( [] >() .mockResolvedValue(getLicenseOrderHistoryInfo), + issueLicense: + issueLicense instanceof Error + ? jest.fn, []>().mockRejectedValue(issueLicense) + : jest + .fn< + Promise<{ + context: Context; + orderedAccountId: number; + myAccountId: number; + tier: number; + poNumber: string; + }>, + [] + >() + .mockResolvedValue(issueLicense), }; }; export const makeUsersRepositoryMock = (value: UsersRepositoryMockValue) => { @@ -228,6 +258,42 @@ export const makeSendGridServiceMock = (value: SendGridMockValue) => { : jest.fn, []>().mockResolvedValue(sendMail), }; }; + +export const makeBlobStorageServiceMock = ( + value: BlobStorageServiceMockValue, +) => { + const { + containerExists, + fileExists, + createContainer, + publishUploadSas, + publishDownloadSas, + } = value; + + return { + containerExists: + containerExists instanceof Error + ? jest.fn, []>().mockRejectedValue(containerExists) + : jest.fn, []>().mockResolvedValue(containerExists), + fileExists: + fileExists instanceof Error + ? jest.fn, []>().mockRejectedValue(fileExists) + : jest.fn, []>().mockResolvedValue(fileExists), + createContainer: + createContainer instanceof Error + ? jest.fn, []>().mockRejectedValue(createContainer) + : jest.fn, []>().mockResolvedValue(createContainer), + publishUploadSas: + publishUploadSas instanceof Error + ? jest.fn, []>().mockRejectedValue(publishUploadSas) + : jest.fn, []>().mockResolvedValue(publishUploadSas), + publishDownloadSas: + publishDownloadSas instanceof Error + ? jest.fn, []>().mockRejectedValue(publishDownloadSas) + : jest.fn, []>().mockResolvedValue(publishDownloadSas), + }; +}; + // 個別のテストケースに対応してそれぞれのMockを用意するのは無駄が多いのでテストケース内で個別の値を設定する export const makeDefaultAccountsRepositoryMockValue = (): AccountsRepositoryMockValue => { @@ -402,5 +468,17 @@ export const makeDefaultLicensesRepositoryMockValue = }, ], }, + issueLicense: undefined, + }; + }; + +export const makeBlobStorageServiceMockValue = + (): BlobStorageServiceMockValue => { + return { + containerExists: true, + fileExists: true, + publishUploadSas: 'https://blob-storage?sas-token', + publishDownloadSas: 'https://blob-storage?sas-token', + createContainer: undefined, }; }; diff --git a/dictation_server/src/features/accounts/test/utility.ts b/dictation_server/src/features/accounts/test/utility.ts index a098ee7..42d5027 100644 --- a/dictation_server/src/features/accounts/test/utility.ts +++ b/dictation_server/src/features/accounts/test/utility.ts @@ -1,9 +1,78 @@ import { DataSource } from 'typeorm'; +import { User } from '../../../repositories/users/entity/user.entity'; import { Account } from '../../../repositories/accounts/entity/account.entity'; import { License, LicenseOrder, } from '../../../repositories/licenses/entity/license.entity'; +import { SortCriteria } from '../../../repositories/sort_criteria/entity/sort_criteria.entity'; + +// TODO: [PBI 2379] 他のUtilityからコピペしてきたもの。後日整理される前提。 +export const createAccountAndAdminUser = async ( + datasource: DataSource, + adminExternalId: string, +): Promise<{ + accountId: number; + adminId: number; + role: string; + tier: number; +}> => { + const { identifiers: account_idf } = await datasource + .getRepository(Account) + .insert({ + tier: 1, + country: 'JP', + delegation_permission: false, + locked: false, + company_name: 'test inc.', + verified: true, + deleted_at: '', + created_by: 'test_runner', + created_at: new Date(), + updated_by: 'updater', + updated_at: new Date(), + }); + const account = account_idf.pop() as Account; + + const { identifiers: user_idf } = await datasource + .getRepository(User) + .insert({ + account_id: account.id, + external_id: adminExternalId, + role: 'admin none', + accepted_terms_version: '1.0', + email_verified: true, + auto_renew: true, + license_alert: true, + notification: true, + encryption: true, + encryption_password: 'password', + prompt: true, + created_by: 'test_runner', + created_at: new Date(), + updated_by: 'updater', + updated_at: new Date(), + }); + const user = user_idf.pop() as User; + + // Accountの管理者を設定する + await datasource.getRepository(Account).update( + { id: user.account_id }, + { + primary_admin_user_id: user.id, + }, + ); + + const accountResult = await getAccount(datasource, account.id); + const userResult = await getUser(datasource, user.id); + + return { + accountId: account.id, + adminId: user.id, + role: userResult.role, + tier: accountResult.tier, + }; +}; export const createAccount = async ( datasource: DataSource, @@ -29,6 +98,80 @@ export const createAccount = async ( return { accountId: account.id }; }; +/** + * テスト ユーティリティ: 指定IDのアカウントを取得する + * @param dataSource データソース + * @param id アカウントID + * @returns 該当アカウント + */ +export const getAccount = async (dataSource: DataSource, id: number) => { + return await dataSource.getRepository(Account).findOne({ + where: { id: id }, + }); +}; + +/** + * テスト ユーティリティ: すべてのアカウントを取得する + * @param dataSource データソース + * @returns 該当アカウント一覧 + */ +export const getAccounts = async ( + dataSource: DataSource, +): Promise => { + return await dataSource.getRepository(Account).find(); +}; + +/** + * テスト ユーティリティ: 指定ExternalIdのユーザーを取得する + * @param dataSource データソース + * @param externalId 外部ID + * @returns 該当ユーザー + */ +export const getUserFromExternalID = async ( + dataSource: DataSource, + externalId: string, +) => { + return await dataSource.getRepository(User).findOne({ + where: { external_id: externalId }, + }); +}; + +/** + * テスト ユーティリティ: 指定Idのユーザーを取得する + * @param dataSource データソース + * @param externalId 外部ID + * @returns 該当ユーザー + */ +export const getUser = async ( + datasource: DataSource, + id: number, +): Promise => { + const user = await datasource.getRepository(User).findOne({ + where: { + id: id, + }, + }); + return user; +}; + +/** + * テスト ユーティリティ: すべてのユーザーを取得する + * @param dataSource データソース + * @returns 該当ユーザー一覧 + */ +export const getUsers = async (dataSource: DataSource): Promise => { + return await dataSource.getRepository(User).find(); +}; + +/** + * テスト ユーティリティ: すべてのソート条件を取得する + * @param dataSource データソース + * @returns 該当ソート条件一覧 + */ +export const getSortCriteria = async (dataSource: DataSource) => { + return await dataSource.getRepository(SortCriteria).find(); +}; + export const createLicense = async ( datasource: DataSource, accountId: number, @@ -50,6 +193,30 @@ export const createLicense = async ( identifiers.pop() as License; }; +// 有効期限・ステータス付きのライセンスを作成 +export const createLicenseSetExpiryDateAndStatus = async ( + datasource: DataSource, + accountId: number, + expiryDate: Date, + status: string, +): Promise => { + const { identifiers } = await datasource.getRepository(License).insert({ + expiry_date: expiryDate, + account_id: accountId, + type: 'NORMAL', + status: status, + allocated_user_id: null, + order_id: null, + deleted_at: null, + delete_order_id: null, + created_by: 'test_runner', + created_at: new Date(), + updated_by: 'updater', + updated_at: new Date(), + }); + identifiers.pop() as License; +}; + export const createLicenseOrder = async ( datasource: DataSource, fromAccountId: number, @@ -74,3 +241,31 @@ export const createLicenseOrder = async ( }); identifiers.pop() as License; }; + +export const createUser = async ( + datasource: DataSource, + accountId: number, + external_id: string, + role: string, + author_id?: string | undefined, +): Promise<{ userId: number; externalId: string; authorId: string }> => { + const { identifiers } = await datasource.getRepository(User).insert({ + account_id: accountId, + external_id: external_id, + role: role, + accepted_terms_version: '1.0', + author_id: author_id, + email_verified: true, + auto_renew: true, + license_alert: true, + notification: true, + encryption: false, + prompt: false, + created_by: 'test_runner', + created_at: new Date(), + updated_by: 'updater', + updated_at: new Date(), + }); + const user = identifiers.pop() as User; + return { userId: user.id, externalId: external_id, authorId: author_id }; +}; diff --git a/dictation_server/src/features/accounts/types/types.ts b/dictation_server/src/features/accounts/types/types.ts index 0f4baf7..fb87e37 100644 --- a/dictation_server/src/features/accounts/types/types.ts +++ b/dictation_server/src/features/accounts/types/types.ts @@ -1,5 +1,15 @@ import { ApiProperty } from '@nestjs/swagger'; -import { IsEmail, IsInt, IsOptional, Matches, Min } from 'class-validator'; +import { + IsEmail, + IsInt, + IsOptional, + Matches, + MaxLength, + Min, + ArrayMinSize, + MinLength, +} from 'class-validator'; +import { IsAdminPasswordvalid } from '../../../common/validators/admin.validator'; export class CreateAccountRequest { @ApiProperty() @@ -10,16 +20,17 @@ export class CreateAccountRequest { maxLength: 2, }) country: string; - @ApiProperty({ nullable: true }) + @ApiProperty({ required: false }) @IsInt() @IsOptional() - dealerAccountId?: number; + dealerAccountId?: number | undefined; @ApiProperty() adminName: string; @ApiProperty() @IsEmail() adminMail: string; @ApiProperty() + @IsAdminPasswordvalid() adminPassword: string; @ApiProperty({ description: '同意済み利用規約のバージョン' }) acceptedTermsVersion: string; @@ -120,6 +131,18 @@ export class GetTypistGroupsResponse { typistGroups: TypistGroup[]; } +export class CreateTypistGroupRequest { + @ApiProperty({ minLength: 1, maxLength: 50 }) + @MinLength(1) + @MaxLength(50) + typistGroupName: string; + @ApiProperty({ minItems: 1 }) + @ArrayMinSize(1) + typistIds: number[]; +} + +export class CreateTypistGroupResponse {} + export class CreatePartnerAccountRequest { @ApiProperty() companyName: string; @@ -189,9 +212,15 @@ export class GetPartnerLicensesResponse { childrenPartnerLicenses: PartnerLicenseInfo[]; } +// 第五階層のshortage算出用 +export class PartnerLicenseInfoForShortage { + expiringSoonLicense?: number; + allocatableLicenseWithMargin?: number; +} + // RepositoryからPartnerLicenseInfoに関する情報を取得する際の型 export type PartnerLicenseInfoForRepository = Omit< - PartnerLicenseInfo, + PartnerLicenseInfo & PartnerLicenseInfoForShortage, 'shortage' >; diff --git a/dictation_server/src/features/files/files.service.spec.ts b/dictation_server/src/features/files/files.service.spec.ts index 556f2f2..8ef77b5 100644 --- a/dictation_server/src/features/files/files.service.spec.ts +++ b/dictation_server/src/features/files/files.service.spec.ts @@ -389,7 +389,7 @@ describe('音声ファイルダウンロードURL取得', () => { it('Typistの場合、自身が担当するタスクでない場合エラー', async () => { const { accountId } = await createAccount(source); - const { externalId, userId } = await createUser( + const { externalId } = await createUser( source, accountId, 'typist-user-external-id', diff --git a/dictation_server/src/features/files/files.service.ts b/dictation_server/src/features/files/files.service.ts index db35646..aaff710 100644 --- a/dictation_server/src/features/files/files.service.ts +++ b/dictation_server/src/features/files/files.service.ts @@ -232,15 +232,11 @@ export class FilesService { try { // 国に応じたリージョンのBlobストレージにコンテナが存在するか確認 - const isContainerExist = await this.blobStorageService.containerExists( + await this.blobStorageService.containerExists( context, accountId, country, ); - //TODO [Task2241] コンテナが無ければ作成しているが、アカウント登録時に作成するので本処理は削除予定。 - if (!isContainerExist) { - await this.blobStorageService.createContainer(accountId, country); - } } catch (e) { this.logger.error(`error=${e}`); this.logger.log( diff --git a/dictation_server/src/features/licenses/licenses.controller.ts b/dictation_server/src/features/licenses/licenses.controller.ts index 9ce59f0..f599211 100644 --- a/dictation_server/src/features/licenses/licenses.controller.ts +++ b/dictation_server/src/features/licenses/licenses.controller.ts @@ -1,6 +1,7 @@ import { Body, Controller, + Get, HttpStatus, Post, Req, @@ -21,6 +22,8 @@ import { IssueCardLicensesRequest, ActivateCardLicensesResponse, ActivateCardLicensesRequest, + GetAllocatableLicensesResponse, + GetAllocatableLicensesRequest, } from './types/types'; import { Request } from 'express'; import { retrieveAuthorizationToken } from '../../common/http/helper'; @@ -29,6 +32,7 @@ import { AuthGuard } from '../../common/guards/auth/authguards'; import { RoleGuard } from '../../common/guards/role/roleguards'; import { ADMIN_ROLES, TIERS } from '../../constants'; import jwt from 'jsonwebtoken'; +import { makeContext } from '../../common/log'; @ApiTags('licenses') @Controller('licenses') @@ -169,4 +173,47 @@ export class LicensesController { return {}; } + + @ApiResponse({ + status: HttpStatus.OK, + type: GetAllocatableLicensesResponse, + description: '成功時のレスポンス', + }) + @ApiResponse({ + status: HttpStatus.UNAUTHORIZED, + description: '認証エラー', + type: ErrorResponse, + }) + @ApiResponse({ + status: HttpStatus.INTERNAL_SERVER_ERROR, + description: '想定外のサーバーエラー', + type: ErrorResponse, + }) + @ApiOperation({ + operationId: 'getAllocatableLicenses', + description: '割り当て可能なライセンスを取得します', + }) + @ApiBearerAuth() + @UseGuards(AuthGuard) + @UseGuards( + RoleGuard.requireds({ roles: [ADMIN_ROLES.ADMIN], tiers: [TIERS.TIER5] }), + ) + @Get('/allocatable') + async getAllocatableLicenses( + // eslint-disable-next-line @typescript-eslint/no-unused-vars + @Req() req: Request, + ): Promise { + const token = retrieveAuthorizationToken(req); + const payload = jwt.decode(token, { json: true }) as AccessToken; + + const context = makeContext(payload.userId); + + const allocatableLicenses = + await this.licensesService.getAllocatableLicenses( + context, + payload.userId, + ); + + return allocatableLicenses; + } } diff --git a/dictation_server/src/features/licenses/licenses.service.spec.ts b/dictation_server/src/features/licenses/licenses.service.spec.ts index 553f2cb..55e0e96 100644 --- a/dictation_server/src/features/licenses/licenses.service.spec.ts +++ b/dictation_server/src/features/licenses/licenses.service.spec.ts @@ -4,6 +4,7 @@ import { IssueCardLicensesRequest, IssueCardLicensesResponse, ActivateCardLicensesRequest, + NewAllocatedLicenseExpirationDate, } from './types/types'; import { makeDefaultAccountsRepositoryMockValue, @@ -27,10 +28,16 @@ import { createCardLicense, createLicense, createCardLicenseIssue, + createLicenseAllocationHistory, selectCardLicensesCount, selectCardLicense, selectLicense, + selectLicenseAllocationHistory, } from './test/utility'; +import { UsersService } from '../users/users.service'; +import { makeContext } from '../../common/log'; +import { IsNotIn } from 'class-validator'; +import { LICENSE_ALLOCATED_STATUS, LICENSE_TYPE } from '../../constants'; describe('LicensesService', () => { it('ライセンス注文が完了する', async () => { @@ -324,11 +331,19 @@ describe('DBテスト', () => { const cardLicenseKey = 'WZCETXC0Z9PQZ9GKRGGY'; const defaultAccountId = 150; - const licenseId = 50; + const license_id = 50; const issueId = 100; - await createLicense(source, licenseId, defaultAccountId); - await createCardLicense(source, licenseId, issueId, cardLicenseKey); + await createLicense( + source, + license_id, + null, + defaultAccountId, + LICENSE_TYPE.CARD, + LICENSE_ALLOCATED_STATUS.UNALLOCATED, + null, + ); + await createCardLicense(source, license_id, issueId, cardLicenseKey); await createCardLicenseIssue(source, issueId); const service = module.get(LicensesService); @@ -338,10 +353,494 @@ describe('DBテスト', () => { source, cardLicenseKey, ); - const dbSelectResultFromLicense = await selectLicense(source, licenseId); + const dbSelectResultFromLicense = await selectLicense(source, license_id); expect( dbSelectResultFromCardLicense.cardLicense.activated_at, ).toBeDefined(); expect(dbSelectResultFromLicense.license.account_id).toEqual(accountId); }); + + it('取込可能なライセンスのみが取得できる', async () => { + const module = await makeTestingModule(source); + + const now = new Date(); + const { accountId } = await createAccount(source); + const { externalId } = await createUser( + source, + accountId, + 'userId', + 'admin', + ); + + // ライセンスを作成する + // 1件目 + await createLicense( + source, + 1, + new Date(now.getTime() + 60 * 60 * 1000), + accountId, + LICENSE_TYPE.NORMAL, + LICENSE_ALLOCATED_STATUS.UNALLOCATED, + null, + ); + // 2件目、expiry_dateがnull(OneYear) + await createLicense( + source, + 2, + null, + accountId, + LICENSE_TYPE.NORMAL, + LICENSE_ALLOCATED_STATUS.UNALLOCATED, + null, + ); + // 3件目、1件目と同じ有効期限 + await createLicense( + source, + 3, + new Date(now.getTime() + 60 * 60 * 1000), + accountId, + LICENSE_TYPE.NORMAL, + LICENSE_ALLOCATED_STATUS.UNALLOCATED, + null, + ); + // 4件目、expiry_dateが一番遠いデータ + await createLicense( + source, + 4, + new Date(now.getTime() + 60 * 60 * 1000 * 2), + accountId, + LICENSE_TYPE.NORMAL, + LICENSE_ALLOCATED_STATUS.UNALLOCATED, + null, + ); + // 5件目、expiry_dateがnull(OneYear) + await createLicense( + source, + 5, + null, + accountId, + LICENSE_TYPE.NORMAL, + LICENSE_ALLOCATED_STATUS.UNALLOCATED, + null, + ); + // 6件目、ライセンス状態が割当済 + await createLicense( + source, + 6, + new Date(now.getTime() + 60 * 60 * 1000 * 2), + accountId, + LICENSE_TYPE.NORMAL, + LICENSE_ALLOCATED_STATUS.ALLOCATED, + null, + ); + // 7件目、ライセンス状態が削除済 + await createLicense( + source, + 7, + new Date(now.getTime() + 60 * 60 * 1000 * 2), + accountId, + LICENSE_TYPE.NORMAL, + LICENSE_ALLOCATED_STATUS.DELETED, + null, + ); + // 8件目、別アカウントの未割当のライセンス + await createLicense( + source, + 8, + new Date(now.getTime() + 60 * 60 * 1000), + accountId + 1, + LICENSE_TYPE.NORMAL, + LICENSE_ALLOCATED_STATUS.UNALLOCATED, + null, + ); + // 9件目、有効期限切れのライセンス + await createLicense( + source, + 9, + new Date(now.getTime() - 60 * 60 * 1000 * 24), + accountId, + LICENSE_TYPE.NORMAL, + LICENSE_ALLOCATED_STATUS.UNALLOCATED, + null, + ); + const service = module.get(LicensesService); + const context = makeContext('userId'); + const response = await service.getAllocatableLicenses(context, externalId); + // 対象外のデータは取得していないことを確認する + expect(response.allocatableLicenses.length).toBe(5); + // ソートして取得されていることを確認する + // (expiry_dateがnullを最優先、次に有効期限が遠い順(同じ有効期限の場合はID昇順) + expect(response.allocatableLicenses[0].licenseId).toBe(2); + expect(response.allocatableLicenses[1].licenseId).toBe(5); + expect(response.allocatableLicenses[2].licenseId).toBe(4); + expect(response.allocatableLicenses[3].licenseId).toBe(1); + expect(response.allocatableLicenses[4].licenseId).toBe(3); + }); +}); + +describe('ライセンス割り当て', () => { + let source: DataSource = null; + beforeEach(async () => { + source = new DataSource({ + type: 'sqlite', + database: ':memory:', + logging: false, + entities: [__dirname + '/../../**/*.entity{.ts,.js}'], + synchronize: true, // trueにすると自動的にmigrationが行われるため注意 + }); + return source.initialize(); + }); + + afterEach(async () => { + await source.destroy(); + source = null; + }); + + it('未割当のライセンスに対して、ライセンス割り当てが完了する', async () => { + const module = await makeTestingModule(source); + + const { accountId } = await createAccount(source); + const { userId } = await createUser(source, accountId, 'userId', 'admin'); + await createLicense( + source, + 1, + null, + accountId, + LICENSE_TYPE.CARD, + LICENSE_ALLOCATED_STATUS.UNALLOCATED, + null, + ); + await createLicenseAllocationHistory(source, 1, userId, 1, 'NONE'); + + const service = module.get(UsersService); + + const expiry_date = new NewAllocatedLicenseExpirationDate(); + + await service.allocateLicense(makeContext('trackingId'), userId, 1); + const resultLicense = await selectLicense(source, 1); + expect(resultLicense.license.allocated_user_id).toBe(userId); + expect(resultLicense.license.status).toBe( + LICENSE_ALLOCATED_STATUS.ALLOCATED, + ); + expect(resultLicense.license.expiry_date.setMilliseconds(0)).toEqual( + expiry_date.setMilliseconds(0), + ); + const licenseAllocationHistory = await selectLicenseAllocationHistory( + source, + userId, + 1, + ); + expect(licenseAllocationHistory.licenseAllocationHistory.user_id).toBe( + userId, + ); + expect(licenseAllocationHistory.licenseAllocationHistory.license_id).toBe( + 1, + ); + expect(licenseAllocationHistory.licenseAllocationHistory.is_allocated).toBe( + true, + ); + }); + + it('再割り当て可能なライセンスに対して、ライセンス割り当てが完了する', async () => { + const module = await makeTestingModule(source); + + const { accountId } = await createAccount(source); + const { userId } = await createUser(source, accountId, 'userId', 'admin'); + const date = new Date(); + date.setDate(date.getDate() + 30); + await createLicense( + source, + 1, + date, + accountId, + LICENSE_TYPE.NORMAL, + LICENSE_ALLOCATED_STATUS.REUSABLE, + null, + ); + await createLicenseAllocationHistory(source, 1, userId, 1, 'NONE'); + + const service = module.get(UsersService); + + await service.allocateLicense(makeContext('trackingId'), userId, 1); + const result = await selectLicense(source, 1); + expect(result.license.allocated_user_id).toBe(userId); + expect(result.license.status).toBe(LICENSE_ALLOCATED_STATUS.ALLOCATED); + expect(result.license.expiry_date).toEqual(date); + const licenseAllocationHistory = await selectLicenseAllocationHistory( + source, + userId, + 1, + ); + expect(licenseAllocationHistory.licenseAllocationHistory.user_id).toBe( + userId, + ); + expect(licenseAllocationHistory.licenseAllocationHistory.license_id).toBe( + 1, + ); + expect(licenseAllocationHistory.licenseAllocationHistory.is_allocated).toBe( + true, + ); + }); + + it('未割当のライセンスに対して、別のライセンスが割り当てられているユーザーの割り当てが完了する', async () => { + const module = await makeTestingModule(source); + + const { accountId } = await createAccount(source); + const { userId } = await createUser(source, accountId, 'userId', 'admin'); + const date = new Date(); + date.setDate(date.getDate() + 30); + await createLicense( + source, + 1, + date, + accountId, + LICENSE_TYPE.NORMAL, + LICENSE_ALLOCATED_STATUS.ALLOCATED, + userId, + ); + await createLicense( + source, + 2, + null, + accountId, + LICENSE_TYPE.CARD, + LICENSE_ALLOCATED_STATUS.UNALLOCATED, + null, + ); + await createLicenseAllocationHistory(source, 1, userId, 1, 'NONE'); + + const service = module.get(UsersService); + + const expiry_date = new NewAllocatedLicenseExpirationDate(); + + await service.allocateLicense(makeContext('trackingId'), userId, 2); + + // もともと割り当てられていたライセンスの状態確認 + const result1 = await selectLicense(source, 1); + expect(result1.license.allocated_user_id).toBe(null); + expect(result1.license.status).toBe(LICENSE_ALLOCATED_STATUS.REUSABLE); + expect(result1.license.expiry_date).toEqual(date); + const licenseAllocationHistory = await selectLicenseAllocationHistory( + source, + userId, + 1, + ); + expect(licenseAllocationHistory.licenseAllocationHistory.user_id).toBe( + userId, + ); + expect(licenseAllocationHistory.licenseAllocationHistory.license_id).toBe( + 1, + ); + expect(licenseAllocationHistory.licenseAllocationHistory.is_allocated).toBe( + false, + ); + + // 新たに割り当てたライセンスの状態確認 + const result2 = await selectLicense(source, 2); + expect(result2.license.allocated_user_id).toBe(userId); + expect(result2.license.status).toBe(LICENSE_ALLOCATED_STATUS.ALLOCATED); + expect(result2.license.expiry_date.setMilliseconds(0)).toEqual( + expiry_date.setMilliseconds(0), + ); + const newlicenseAllocationHistory = await selectLicenseAllocationHistory( + source, + userId, + 2, + ); + expect(newlicenseAllocationHistory.licenseAllocationHistory.user_id).toBe( + userId, + ); + expect( + newlicenseAllocationHistory.licenseAllocationHistory.license_id, + ).toBe(2); + expect( + newlicenseAllocationHistory.licenseAllocationHistory.is_allocated, + ).toBe(true); + }); + + it('割り当て時にライセンス履歴テーブルへの登録が完了する(元がNORMALのとき)', async () => { + const module = await makeTestingModule(source); + + const { accountId } = await createAccount(source); + const { userId } = await createUser(source, accountId, 'userId', 'admin'); + const date = new Date(); + date.setDate(date.getDate() + 30); + await createLicense( + source, + 1, + date, + accountId, + LICENSE_TYPE.NORMAL, + LICENSE_ALLOCATED_STATUS.ALLOCATED, + userId, + ); + await createLicense( + source, + 2, + null, + accountId, + LICENSE_TYPE.CARD, + LICENSE_ALLOCATED_STATUS.UNALLOCATED, + null, + ); + await createLicenseAllocationHistory(source, 1, userId, 1, 'NONE'); + + const service = module.get(UsersService); + await service.allocateLicense(makeContext('trackingId'), userId, 2); + + const licenseAllocationHistory = await selectLicenseAllocationHistory( + source, + userId, + 2, + ); + expect( + licenseAllocationHistory.licenseAllocationHistory.switch_from_type, + ).toBe('NONE'); + }); + + it('割り当て時にライセンス履歴テーブルへの登録が完了する(元がCARDのとき)', async () => { + const module = await makeTestingModule(source); + + const { accountId } = await createAccount(source); + const { userId } = await createUser(source, accountId, 'userId', 'admin'); + const date = new Date(); + date.setDate(date.getDate() + 30); + await createLicense( + source, + 1, + date, + accountId, + LICENSE_TYPE.CARD, + LICENSE_ALLOCATED_STATUS.ALLOCATED, + userId, + ); + await createLicense( + source, + 2, + null, + accountId, + LICENSE_TYPE.CARD, + LICENSE_ALLOCATED_STATUS.UNALLOCATED, + null, + ); + await createLicenseAllocationHistory(source, 1, userId, 1, 'CARD'); + + const service = module.get(UsersService); + await service.allocateLicense(makeContext('trackingId'), userId, 2); + + const licenseAllocationHistory = await selectLicenseAllocationHistory( + source, + userId, + 2, + ); + expect( + licenseAllocationHistory.licenseAllocationHistory.switch_from_type, + ).toBe('CARD'); + }); + + it('割り当て時にライセンス履歴テーブルへの登録が完了する(元がTRIALのとき)', async () => { + const module = await makeTestingModule(source); + + const { accountId } = await createAccount(source); + const { userId } = await createUser(source, accountId, 'userId', 'admin'); + const date = new Date(); + date.setDate(date.getDate() + 30); + await createLicense( + source, + 1, + date, + accountId, + LICENSE_TYPE.TRIAL, + LICENSE_ALLOCATED_STATUS.ALLOCATED, + userId, + ); + await createLicense( + source, + 2, + null, + accountId, + LICENSE_TYPE.CARD, + LICENSE_ALLOCATED_STATUS.UNALLOCATED, + null, + ); + await createLicenseAllocationHistory(source, 1, userId, 1, 'TRIAL'); + + const service = module.get(UsersService); + await service.allocateLicense(makeContext('trackingId'), userId, 2); + + const licenseAllocationHistory = await selectLicenseAllocationHistory( + source, + userId, + 2, + ); + expect( + licenseAllocationHistory.licenseAllocationHistory.switch_from_type, + ).toBe('TRIAL'); + }); + + it('有効期限が切れているライセンスを割り当てようとした場合、エラーになる', async () => { + const module = await makeTestingModule(source); + + const { accountId } = await createAccount(source); + const { userId } = await createUser(source, accountId, 'userId', 'admin'); + const date = new Date(); + date.setDate(date.getDate() - 30); + await createLicense( + source, + 1, + date, + accountId, + LICENSE_TYPE.NORMAL, + LICENSE_ALLOCATED_STATUS.REUSABLE, + null, + ); + + const service = module.get(UsersService); + + await expect( + service.allocateLicense(makeContext('trackingId'), userId, 1), + ).rejects.toEqual( + new HttpException(makeErrorResponse('E010805'), HttpStatus.BAD_REQUEST), + ); + }); + + it('割り当て不可なライセンスを割り当てようとした場合、エラーになる', async () => { + const module = await makeTestingModule(source); + + const { accountId } = await createAccount(source); + const { userId } = await createUser(source, accountId, 'userId', 'admin'); + const date = new Date(); + date.setDate(date.getDate() + 30); + await createLicense( + source, + 1, + null, + accountId, + LICENSE_TYPE.NORMAL, + LICENSE_ALLOCATED_STATUS.ALLOCATED, + null, + ); + await createLicense( + source, + 2, + null, + accountId, + LICENSE_TYPE.NORMAL, + LICENSE_ALLOCATED_STATUS.DELETED, + null, + ); + + const service = module.get(UsersService); + + await expect( + service.allocateLicense(makeContext('trackingId'), userId, 1), + ).rejects.toEqual( + new HttpException(makeErrorResponse('E010806'), HttpStatus.BAD_REQUEST), + ); + await expect( + service.allocateLicense(makeContext('trackingId'), userId, 2), + ).rejects.toEqual( + new HttpException(makeErrorResponse('E010806'), HttpStatus.BAD_REQUEST), + ); + }); }); diff --git a/dictation_server/src/features/licenses/licenses.service.ts b/dictation_server/src/features/licenses/licenses.service.ts index 2c13742..a60e4fd 100644 --- a/dictation_server/src/features/licenses/licenses.service.ts +++ b/dictation_server/src/features/licenses/licenses.service.ts @@ -11,7 +11,11 @@ import { } from '../../repositories/licenses/errors/types'; import { LicensesRepositoryService } from '../../repositories/licenses/licenses.repository.service'; import { UserNotFoundError } from '../../repositories/users/errors/types'; -import { IssueCardLicensesResponse } from './types/types'; +import { + GetAllocatableLicensesResponse, + IssueCardLicensesResponse, +} from './types/types'; +import { Context } from '../../common/log'; @Injectable() export class LicensesService { @@ -211,4 +215,44 @@ export class LicensesService { this.logger.log(`[OUT] ${this.activateCardLicenseKey.name}`); return; } + + /** + * get allocatable lisences + * @param context + * @param userId + * @@returns AllocatableLicenseInfo[] + */ + async getAllocatableLicenses( + context: Context, + userId: string, + ): Promise { + this.logger.log( + `[IN] [${context.trackingId}] ${this.getAllocatableLicenses.name} | params: { ` + + `userId: ${userId}, `, + ); + // ユーザIDからアカウントIDを取得する + try { + const myAccountId = ( + await this.usersRepository.findUserByExternalId(userId) + ).account_id; + // 割り当て可能なライセンスを取得する + const allocatableLicenses = + await this.licensesRepository.getAllocatableLicenses(myAccountId); + + return { + allocatableLicenses, + }; + } catch (e) { + this.logger.error(`error=${e}`); + this.logger.error('get allocatable lisences failed'); + throw new HttpException( + makeErrorResponse('E009999'), + HttpStatus.INTERNAL_SERVER_ERROR, + ); + } finally { + this.logger.log( + `[OUT] [${context.trackingId}] ${this.getAllocatableLicenses.name}`, + ); + } + } } diff --git a/dictation_server/src/features/licenses/test/utility.ts b/dictation_server/src/features/licenses/test/utility.ts index 7ff55f0..352c974 100644 --- a/dictation_server/src/features/licenses/test/utility.ts +++ b/dictation_server/src/features/licenses/test/utility.ts @@ -5,6 +5,7 @@ import { License, CardLicense, CardLicenseIssue, + LicenseAllocationHistory, } from '../../../repositories/licenses/entity/license.entity'; export const createAccount = async ( @@ -58,15 +59,19 @@ export const createUser = async ( export const createLicense = async ( datasource: DataSource, licenseId: number, + expiry_date: Date, accountId: number, + type: string, + status: string, + allocated_user_id: number, ): Promise => { const { identifiers } = await datasource.getRepository(License).insert({ id: licenseId, - expiry_date: null, + expiry_date: expiry_date, account_id: accountId, - type: 'card', - status: 'Unallocated', - allocated_user_id: null, + type: type, + status: status, + allocated_user_id: allocated_user_id, order_id: null, deleted_at: null, delete_order_id: null, @@ -114,6 +119,31 @@ export const createCardLicenseIssue = async ( identifiers.pop() as CardLicenseIssue; }; +export const createLicenseAllocationHistory = async ( + datasource: DataSource, + historyId: number, + userId: number, + licenseId: number, + type: string, +): Promise => { + const { identifiers } = await datasource + .getRepository(LicenseAllocationHistory) + .insert({ + id: historyId, + user_id: userId, + license_id: licenseId, + is_allocated: true, + executed_at: new Date(), + switch_from_type: type, + deleted_at: null, + created_by: null, + created_at: new Date(), + updated_by: null, + updated_at: new Date(), + }); + identifiers.pop() as LicenseAllocationHistory; +}; + export const selectCardLicensesCount = async ( datasource: DataSource, ): Promise<{ count: number }> => { @@ -144,3 +174,22 @@ export const selectLicense = async ( }); return { license }; }; + +export const selectLicenseAllocationHistory = async ( + datasource: DataSource, + userId: number, + licence_id: number, +): Promise<{ licenseAllocationHistory: LicenseAllocationHistory }> => { + const licenseAllocationHistory = await datasource + .getRepository(LicenseAllocationHistory) + .findOne({ + where: { + user_id: userId, + license_id: licence_id, + }, + order: { + executed_at: 'DESC', + }, + }); + return { licenseAllocationHistory }; +}; diff --git a/dictation_server/src/features/licenses/types/types.ts b/dictation_server/src/features/licenses/types/types.ts index a4df377..e0fce77 100644 --- a/dictation_server/src/features/licenses/types/types.ts +++ b/dictation_server/src/features/licenses/types/types.ts @@ -1,5 +1,10 @@ import { ApiProperty } from '@nestjs/swagger'; import { IsInt, Matches, Max, Min, Length } from 'class-validator'; +import { + LICENSE_EXPIRATION_DAYS, + LICENSE_EXPIRATION_THRESHOLD_DAYS, + TRIAL_LICENSE_EXPIRATION_DAYS, +} from '../../../constants'; export class CreateOrdersRequest { @ApiProperty() @@ -37,6 +42,19 @@ export class ActivateCardLicensesRequest { export class ActivateCardLicensesResponse {} +export class GetAllocatableLicensesRequest {} + +export class AllocatableLicenseInfo { + @ApiProperty() + licenseId: number; + @ApiProperty() + expiryDate: Date; +} +export class GetAllocatableLicensesResponse { + @ApiProperty({ type: [AllocatableLicenseInfo] }) + allocatableLicenses: AllocatableLicenseInfo[]; +} + // ライセンス算出用に、その日の始まりの時刻(0:00:00.000)の日付を取得する export class DateWithZeroTime extends Date { constructor(...args: any[]) { @@ -48,3 +66,44 @@ export class DateWithZeroTime extends Date { this.setHours(0, 0, 0, 0); // 時分秒を"0:00:00.000"に固定 } } + +// ライセンスの算出用に、閾値となる時刻(23:59:59.999)の日付を取得する +export class ExpirationThresholdDate extends Date { + constructor(...args: any[]) { + if (args.length === 0) { + super(); // 引数がない場合、現在の日付で初期化 + } else { + super(...(args as [string])); // 引数がある場合、引数をそのままDateクラスのコンストラクタに渡す + } + this.setDate(this.getDate() + LICENSE_EXPIRATION_THRESHOLD_DAYS); + this.setHours(23, 59, 59, 999); // 時分秒を"23:59:59.999"に固定 + } +} + +// 新規トライアルライセンス発行時の有効期限算出用に、30日後の日付を取得する +export class NewTrialLicenseExpirationDate extends Date { + constructor(...args: any[]) { + if (args.length === 0) { + super(); // 引数がない場合、現在の日付で初期化 + } else { + super(...(args as [string])); // 引数がある場合、引数をそのままDateクラスのコンストラクタに渡す + } + this.setDate(this.getDate() + TRIAL_LICENSE_EXPIRATION_DAYS); + this.setHours(23, 59, 59); // 時分秒を"23:59:59"に固定 + this.setMilliseconds(0); + } +} + +// 新規ライセンス割り当て時の有効期限算出用に、365日後の日付を取得する +export class NewAllocatedLicenseExpirationDate extends Date { + constructor(...args: any[]) { + if (args.length === 0) { + super(); // 引数がない場合、現在の日付で初期化 + } else { + super(...(args as [string])); // 引数がある場合、引数をそのままDateクラスのコンストラクタに渡す + } + this.setDate(this.getDate() + LICENSE_EXPIRATION_DAYS); + this.setHours(23, 59, 59); // 時分秒を"23:59:59"に固定 + this.setMilliseconds(0); + } +} diff --git a/dictation_server/src/features/users/test/users.service.mock.ts b/dictation_server/src/features/users/test/users.service.mock.ts index 8076a52..4882ce2 100644 --- a/dictation_server/src/features/users/test/users.service.mock.ts +++ b/dictation_server/src/features/users/test/users.service.mock.ts @@ -8,6 +8,7 @@ import { import { SendGridService } from '../../../gateways/sendgrid/sendgrid.service'; import { User } from '../../../repositories/users/entity/user.entity'; import { UsersRepositoryService } from '../../../repositories/users/users.repository.service'; +import { LicensesRepositoryService } from '../../../repositories/licenses/licenses.repository.service'; import { UsersService } from '../users.service'; import { SortCriteria } from '../../../repositories/sort_criteria/entity/sort_criteria.entity'; import { SortCriteriaRepositoryService } from '../../../repositories/sort_criteria/sort_criteria.repository.service'; @@ -31,6 +32,10 @@ export type UsersRepositoryMockValue = { existsAuthorId: boolean | Error; }; +export type LicensesRepositoryMockValue = { + // empty +}; + export type AdB2cMockValue = { getMetaData: B2cMetadata | Error; getSignKeySets: JwkSignKey[] | Error; @@ -58,6 +63,7 @@ export type ConfigMockValue = { export const makeUsersServiceMock = async ( usersRepositoryMockValue: UsersRepositoryMockValue, + licensesRepositoryMockValue: LicensesRepositoryMockValue, adB2cMockValue: AdB2cMockValue, sendGridMockValue: SendGridMockValue, configMockValue: ConfigMockValue, @@ -75,6 +81,8 @@ export const makeUsersServiceMock = async ( switch (token) { case UsersRepositoryService: return makeUsersRepositoryMock(usersRepositoryMockValue); + case LicensesRepositoryService: + return makeLicensesRepositoryMock(); case AdB2cService: return makeAdB2cServiceMock(adB2cMockValue); case SendGridService: @@ -239,6 +247,12 @@ export const makeUsersRepositoryMock = (value: UsersRepositoryMockValue) => { }; }; +export const makeLicensesRepositoryMock = (): LicensesRepositoryMockValue => { + return { + // empty + }; +}; + export const makeSendGridMock = (value: SendGridMockValue) => { const { sendMail, createMailContentFromEmailConfirmForNormalUser } = value; @@ -283,7 +297,7 @@ export const makeDefaultSendGridlValue = (): SendGridMockValue => { export const makeDefaultConfigValue = (): ConfigMockValue => { return { - get: `test@example.co.jp`, + get: `test@example.com`, }; }; diff --git a/dictation_server/src/features/users/test/utility.ts b/dictation_server/src/features/users/test/utility.ts index 31a8a34..4452f61 100644 --- a/dictation_server/src/features/users/test/utility.ts +++ b/dictation_server/src/features/users/test/utility.ts @@ -38,6 +38,72 @@ import { AdB2cMockValue, makeAdB2cServiceMock } from './users.service.mock'; import { AdB2cService } from '../../../gateways/adb2c/adb2c.service'; import { LICENSE_ALLOCATED_STATUS, LICENSE_TYPE } from '../../../constants'; +export const createAccountAndAdminUser = async ( + datasource: DataSource, + adminExternalId: string, +): Promise<{ + accountId: number; + adminId: number; + role: string; + tier: number; +}> => { + const { identifiers: account_idf } = await datasource + .getRepository(Account) + .insert({ + tier: 1, + country: 'JP', + delegation_permission: false, + locked: false, + company_name: 'test inc.', + verified: true, + deleted_at: '', + created_by: 'test_runner', + created_at: new Date(), + updated_by: 'updater', + updated_at: new Date(), + }); + const account = account_idf.pop() as Account; + + const { identifiers: user_idf } = await datasource + .getRepository(User) + .insert({ + account_id: account.id, + external_id: adminExternalId, + role: 'admin none', + accepted_terms_version: '1.0', + email_verified: true, + auto_renew: true, + license_alert: true, + notification: true, + encryption: true, + encryption_password: 'password', + prompt: true, + created_by: 'test_runner', + created_at: new Date(), + updated_by: 'updater', + updated_at: new Date(), + }); + const user = user_idf.pop() as User; + + // Accountの管理者を設定する + await datasource.getRepository(Account).update( + { id: user.account_id }, + { + primary_admin_user_id: user.id, + }, + ); + + const accountResult = await getAccount(datasource, account.id); + const userResult = await getUser(datasource, user.id); + + return { + accountId: account.id, + adminId: user.id, + role: userResult.role, + tier: accountResult.tier, + }; +}; + export const createAccount = async ( datasource: DataSource, ): Promise<{ accountId: number }> => { @@ -68,6 +134,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 +142,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, @@ -91,6 +158,18 @@ export const createUser = async ( return { userId: user.id, externalId: external_id }; }; +/** + * テスト ユーティリティ: 指定IDのアカウントを取得する + * @param dataSource データソース + * @param id アカウントID + * @returns 該当アカウント + */ +export const getAccount = async (dataSource: DataSource, id: number) => { + return await dataSource.getRepository(Account).findOne({ + where: { id: id }, + }); +}; + export const getUser = async ( datasource: DataSource, id: number, @@ -103,6 +182,45 @@ 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; +}; + +/** + * テスト ユーティリティ: 指定外部IDを持つユーザーを取得する + * @param dataSource データソース + * @param externalId 外部ID + * @returns 該当ユーザー + */ +export const getUserByExternalId = async ( + datasource: DataSource, + externalId: string, +): Promise => { + const user = await datasource.getRepository(User).findOne({ + where: { + external_id: externalId, + }, + }); + return user; +}; + +/** + * テスト ユーティリティ: すべてのユーザーを取得する + * @param dataSource データソース + * @returns 該当ユーザー一覧 + */ +export const getUsers = async (dataSource: DataSource): Promise => { + return await dataSource.getRepository(User).find(); +}; + /** * * @param datasource diff --git a/dictation_server/src/features/users/types/types.ts b/dictation_server/src/features/users/types/types.ts index d70d6ac..42f1a97 100644 --- a/dictation_server/src/features/users/types/types.ts +++ b/dictation_server/src/features/users/types/types.ts @@ -239,3 +239,19 @@ export class PostUpdateUserRequest { } export class PostUpdateUserResponse {} + +export class AllocateLicenseRequest { + @ApiProperty({ description: 'ユーザーID' }) + userId: number; + @ApiProperty({ description: '割り当てるライセンスのID' }) + newLicenseId: number; +} + +export class AllocateLicenseResponse {} + +export class DeallocateLicenseRequest { + @ApiProperty({ description: 'ユーザーID' }) + userId: number; +} + +export class DeallocateLicenseResponse {} diff --git a/dictation_server/src/features/users/users.controller.ts b/dictation_server/src/features/users/users.controller.ts index f908b6d..bb7b589 100644 --- a/dictation_server/src/features/users/users.controller.ts +++ b/dictation_server/src/features/users/users.controller.ts @@ -33,6 +33,10 @@ import { GetSortCriteriaResponse, PostUpdateUserRequest, PostUpdateUserResponse, + AllocateLicenseResponse, + AllocateLicenseRequest, + DeallocateLicenseResponse, + DeallocateLicenseRequest, } from './types/types'; import { UsersService } from './users.service'; import jwt from 'jsonwebtoken'; @@ -41,10 +45,11 @@ import { isSortDirection, isTaskListSortableAttribute, } from '../../common/types/sort'; -import { ADMIN_ROLES } from '../../constants'; +import { ADMIN_ROLES, TIERS } from '../../constants'; import { RoleGuard } from '../../common/guards/role/roleguards'; import { makeContext } from '../../common/log'; import { UserRoles } from '../../common/types/role'; +import { v4 as uuidv4 } from 'uuid'; @ApiTags('users') @Controller('users') @@ -93,8 +98,8 @@ export class UsersController { async confirmUserAndInitPassword( @Body() body: ConfirmRequest, ): Promise { - console.log(body); - await this.usersService.confirmUserAndInitPassword(body.token); + const context = makeContext(uuidv4()); + await this.usersService.confirmUserAndInitPassword(context, body.token); return {}; } @@ -171,8 +176,11 @@ export class UsersController { const accessToken = retrieveAuthorizationToken(req); const payload = jwt.decode(accessToken, { json: true }) as AccessToken; + const context = makeContext(payload.userId); + //ユーザ作成処理 await this.usersService.createUser( + context, payload, name, role as UserRoles, @@ -372,4 +380,94 @@ export class UsersController { ); return {}; } + + @ApiResponse({ + status: HttpStatus.OK, + type: AllocateLicenseResponse, + description: '成功時のレスポンス', + }) + @ApiResponse({ + status: HttpStatus.BAD_REQUEST, + description: '割り当て失敗時', + type: ErrorResponse, + }) + @ApiResponse({ + status: HttpStatus.UNAUTHORIZED, + description: '認証エラー', + type: ErrorResponse, + }) + @ApiResponse({ + status: HttpStatus.INTERNAL_SERVER_ERROR, + description: '想定外のサーバーエラー', + type: ErrorResponse, + }) + @ApiOperation({ + operationId: 'allocateLicense', + description: 'ライセンスを割り当てます', + }) + @ApiBearerAuth() + @UseGuards(AuthGuard) + @UseGuards( + RoleGuard.requireds({ roles: [ADMIN_ROLES.ADMIN], tiers: [TIERS.TIER5] }), + ) + @Post('/license/allocate') + async allocateLicense( + @Body() body: AllocateLicenseRequest, + @Req() req: Request, + ): Promise { + const accessToken = retrieveAuthorizationToken(req); + const { userId } = jwt.decode(accessToken, { json: true }) as AccessToken; + + const context = makeContext(userId); + await this.usersService.allocateLicense( + context, + body.userId, + body.newLicenseId, + ); + return {}; + } + + @ApiResponse({ + status: HttpStatus.OK, + type: DeallocateLicenseResponse, + description: '成功時のレスポンス', + }) + @ApiResponse({ + status: HttpStatus.BAD_REQUEST, + description: 'すでにライセンスが割り当て解除されている時', + type: ErrorResponse, + }) + @ApiResponse({ + status: HttpStatus.UNAUTHORIZED, + description: '認証エラー', + type: ErrorResponse, + }) + @ApiResponse({ + status: HttpStatus.INTERNAL_SERVER_ERROR, + description: '想定外のサーバーエラー', + type: ErrorResponse, + }) + @ApiOperation({ + operationId: 'deallocateLicense', + description: 'ライセンス割り当てを解除します', + }) + @ApiBearerAuth() + @UseGuards(AuthGuard) + @UseGuards( + RoleGuard.requireds({ roles: [ADMIN_ROLES.ADMIN], tiers: [TIERS.TIER5] }), + ) + @Post('/license/deallocate') + async deallocateLicense( + @Body() body: DeallocateLicenseRequest, + @Req() req: Request, + ): Promise { + //API実装時に詳細をかいていく + //const accessToken = retrieveAuthorizationToken(req); + //const { userId } = jwt.decode(accessToken, { json: true }) as AccessToken; + + //const context = makeContext(userId); + + //await this.usersService.deallocateLicense(context, body.userId); + return {}; + } } diff --git a/dictation_server/src/features/users/users.module.ts b/dictation_server/src/features/users/users.module.ts index febd59f..e4ae006 100644 --- a/dictation_server/src/features/users/users.module.ts +++ b/dictation_server/src/features/users/users.module.ts @@ -4,12 +4,14 @@ import { AdB2cModule } from '../../gateways/adb2c/adb2c.module'; import { SendGridModule } from '../../gateways/sendgrid/sendgrid.module'; import { SortCriteriaRepositoryModule } from '../../repositories/sort_criteria/sort_criteria.repository.module'; import { UsersRepositoryModule } from '../../repositories/users/users.repository.module'; +import { LicensesRepositoryModule } from '../../repositories/licenses/licenses.repository.module'; import { UsersController } from './users.controller'; import { UsersService } from './users.service'; @Module({ imports: [ UsersRepositoryModule, + LicensesRepositoryModule, SortCriteriaRepositoryModule, AdB2cModule, SendGridModule, diff --git a/dictation_server/src/features/users/users.service.spec.ts b/dictation_server/src/features/users/users.service.spec.ts index 2565b0d..fa18ab9 100644 --- a/dictation_server/src/features/users/users.service.spec.ts +++ b/dictation_server/src/features/users/users.service.spec.ts @@ -12,41 +12,176 @@ import { import { EmailAlreadyVerifiedError } from '../../repositories/users/errors/types'; import { createAccount, + createAccountAndAdminUser, createLicense, createUser, createUserGroup, + getLicenses, getUser, + getUserByExternalId, + getUsers, makeTestingModuleWithAdb2c, } from './test/utility'; import { DataSource } from 'typeorm'; import { UsersService } from './users.service'; import { + LICENSE_ALLOCATED_STATUS, LICENSE_EXPIRATION_THRESHOLD_DAYS, + LICENSE_TYPE, USER_LICENSE_STATUS, USER_ROLES, } from '../../constants'; import { makeTestingModule } from '../../common/test/modules'; +import { Context, makeContext } from '../../common/log'; +import { + overrideAdB2cService, + overrideSendgridService, + overrideUsersRepositoryService, +} from '../../common/test/overrides'; +import { NewTrialLicenseExpirationDate } from '../licenses/types/types'; +import { License } from '../../repositories/licenses/entity/license.entity'; +import { AdB2cService } from '../../gateways/adb2c/adb2c.service'; describe('UsersService.confirmUser', () => { - it('ユーザの仮登録時に払い出されるトークンにより、未認証のユーザが認証済みになる', async () => { - const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue(); - const adb2cParam = makeDefaultAdB2cMockValue(); - const sendGridMockValue = makeDefaultSendGridlValue(); - const configMockValue = makeDefaultConfigValue(); - const sortCriteriaRepositoryMockValue = - makeDefaultSortCriteriaRepositoryMockValue(); - const service = await makeUsersServiceMock( - usersRepositoryMockValue, - 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); + + // トライアルライセンスは有効期限は今日を起算日として30日後の日付が変わるまで + const expiryDate = new NewTrialLicenseExpirationDate(); + 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 = { @@ -66,6 +201,7 @@ describe('UsersService.confirmUser', () => { encryption: false, prompt: false, }; + const licensesRepositoryMockValue = null; const adb2cParam = makeDefaultAdB2cMockValue(); const configMockValue = makeDefaultConfigValue(); const sortCriteriaRepositoryMockValue = @@ -73,6 +209,7 @@ describe('UsersService.confirmUser', () => { const sendGridMockValue = makeDefaultSendGridlValue(); const service = await makeUsersServiceMock( usersRepositoryMockValue, + licensesRepositoryMockValue, adb2cParam, sendGridMockValue, configMockValue, @@ -81,27 +218,12 @@ describe('UsersService.confirmUser', () => { const token = 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2NvdW50SWQiOjEsInVzZXJJZCI6MiwiZW1haWwiOiJ4eHhAeHh4Lnh4eCIsImlhdCI6MTAwMDAwMDAwMCwiZXhwIjo5MDAwMDAwMDAwfQ.26L6BdNg-3TbyKT62PswlJ6RPMkcTtHzlDXW2Uo9XbMPVSrl2ObcuS6EcXjFFN2DEfNTKbqX_zevIWMpHOAdLNgGhk528nLrBrNvPASqtTjvW9muxMXpjUdjRVkmVbOylBHWW3YpWL9JEbJQ7rAzWDfaIdPhMovdaxumnZt_UwnlnrdaVPLACW7tkH_laEcAU507iSiM4mqxxG8FuTs34t6PEdwRuzZAQPN2IOPYNSvGNdJYryPacSeSNZ_z1xeBYXLOLQfOBZzyTReYDOhXdikhrNUbxjgnZQlSXBCVMlZ9PH42bHfp-LJIeJzW0yqnF6oLklvJP-fo8eW0k5iDOw'; - expect(await service.confirmUserAndInitPassword(token)).toEqual(undefined); - }); - - it('トークンの形式が不正な場合、形式不正エラーとなる。', async () => { - const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue(); - const adb2cParam = makeDefaultAdB2cMockValue(); - const sendgridMockValue = makeDefaultSendGridlValue(); - const configMockValue = makeDefaultConfigValue(); - const sortCriteriaRepositoryMockValue = - makeDefaultSortCriteriaRepositoryMockValue(); - const service = await makeUsersServiceMock( - usersRepositoryMockValue, - adb2cParam, - sendgridMockValue, - configMockValue, - sortCriteriaRepositoryMockValue, - ); - const token = 'invalid.id.token'; - await expect(service.confirmUser(token)).rejects.toEqual( - new HttpException(makeErrorResponse('E000101'), HttpStatus.BAD_REQUEST), - ); + expect( + await service.confirmUserAndInitPassword( + makeContext('trackingId'), + token, + ), + ).toEqual(undefined); }); it('トークンの形式が不正な場合、形式不正エラーとなる。(メール認証API)', async () => { @@ -123,6 +245,7 @@ describe('UsersService.confirmUser', () => { encryption: false, prompt: false, }; + const licensesRepositoryMockValue = null; const adb2cParam = makeDefaultAdB2cMockValue(); const sendGridMockValue = makeDefaultSendGridlValue(); const configMockValue = makeDefaultConfigValue(); @@ -130,40 +253,19 @@ describe('UsersService.confirmUser', () => { makeDefaultSortCriteriaRepositoryMockValue(); const service = await makeUsersServiceMock( usersRepositoryMockValue, + licensesRepositoryMockValue, adb2cParam, sendGridMockValue, configMockValue, sortCriteriaRepositoryMockValue, ); const token = 'invalid.id.token'; - await expect(service.confirmUserAndInitPassword(token)).rejects.toEqual( + await expect( + service.confirmUserAndInitPassword(makeContext('trackingId'), token), + ).rejects.toEqual( new HttpException(makeErrorResponse('E000101'), HttpStatus.BAD_REQUEST), ); }); - it('ユーザが既に認証済みだった場合、認証済みユーザエラーとなる。', async () => { - const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue(); - const adb2cParam = makeDefaultAdB2cMockValue(); - const sendgridMockValue = makeDefaultSendGridlValue(); - const configMockValue = makeDefaultConfigValue(); - const sortCriteriaRepositoryMockValue = - makeDefaultSortCriteriaRepositoryMockValue(); - - usersRepositoryMockValue.updateUserVerified = - new EmailAlreadyVerifiedError(); - - const service = await makeUsersServiceMock( - usersRepositoryMockValue, - 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 = { @@ -183,6 +285,7 @@ describe('UsersService.confirmUser', () => { encryption: false, prompt: false, }; + const licensesRepositoryMockValue = null; const adb2cParam = makeDefaultAdB2cMockValue(); const sendGridMockValue = makeDefaultSendGridlValue(); const configMockValue = makeDefaultConfigValue(); @@ -193,6 +296,7 @@ describe('UsersService.confirmUser', () => { const service = await makeUsersServiceMock( usersRepositoryMockValue, + licensesRepositoryMockValue, adb2cParam, sendGridMockValue, configMockValue, @@ -200,35 +304,12 @@ describe('UsersService.confirmUser', () => { ); const token = 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2NvdW50SWQiOjEsInVzZXJJZCI6MiwiZW1haWwiOiJ4eHhAeHh4Lnh4eCIsImlhdCI6MTAwMDAwMDAwMCwiZXhwIjo5MDAwMDAwMDAwfQ.26L6BdNg-3TbyKT62PswlJ6RPMkcTtHzlDXW2Uo9XbMPVSrl2ObcuS6EcXjFFN2DEfNTKbqX_zevIWMpHOAdLNgGhk528nLrBrNvPASqtTjvW9muxMXpjUdjRVkmVbOylBHWW3YpWL9JEbJQ7rAzWDfaIdPhMovdaxumnZt_UwnlnrdaVPLACW7tkH_laEcAU507iSiM4mqxxG8FuTs34t6PEdwRuzZAQPN2IOPYNSvGNdJYryPacSeSNZ_z1xeBYXLOLQfOBZzyTReYDOhXdikhrNUbxjgnZQlSXBCVMlZ9PH42bHfp-LJIeJzW0yqnF6oLklvJP-fo8eW0k5iDOw'; - await expect(service.confirmUserAndInitPassword(token)).rejects.toEqual( + await expect( + service.confirmUserAndInitPassword(makeContext('trackingId'), token), + ).rejects.toEqual( new HttpException(makeErrorResponse('E010202'), HttpStatus.BAD_REQUEST), ); }); - it('DBネットワークエラーとなる場合、エラーとなる。', async () => { - const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue(); - const adb2cParam = makeDefaultAdB2cMockValue(); - const sendgridMockValue = makeDefaultSendGridlValue(); - const configMockValue = makeDefaultConfigValue(); - const sortCriteriaRepositoryMockValue = - makeDefaultSortCriteriaRepositoryMockValue(); - usersRepositoryMockValue.updateUserVerified = new Error('DB error'); - - const service = await makeUsersServiceMock( - usersRepositoryMockValue, - 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 = { @@ -248,6 +329,7 @@ describe('UsersService.confirmUser', () => { encryption: false, prompt: false, }; + const licensesRepositoryMockValue = null; const adb2cParam = makeDefaultAdB2cMockValue(); const sendGridMockValue = makeDefaultSendGridlValue(); usersRepositoryMockValue.updateUserVerified = new Error('DB error'); @@ -256,6 +338,7 @@ describe('UsersService.confirmUser', () => { makeDefaultSortCriteriaRepositoryMockValue(); const service = await makeUsersServiceMock( usersRepositoryMockValue, + licensesRepositoryMockValue, adb2cParam, sendGridMockValue, configMockValue, @@ -263,36 +346,86 @@ describe('UsersService.confirmUser', () => { ); const token = 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2NvdW50SWQiOjEsInVzZXJJZCI6MiwiZW1haWwiOiJ4eHhAeHh4Lnh4eCIsImlhdCI6MTAwMDAwMDAwMCwiZXhwIjo5MDAwMDAwMDAwfQ.26L6BdNg-3TbyKT62PswlJ6RPMkcTtHzlDXW2Uo9XbMPVSrl2ObcuS6EcXjFFN2DEfNTKbqX_zevIWMpHOAdLNgGhk528nLrBrNvPASqtTjvW9muxMXpjUdjRVkmVbOylBHWW3YpWL9JEbJQ7rAzWDfaIdPhMovdaxumnZt_UwnlnrdaVPLACW7tkH_laEcAU507iSiM4mqxxG8FuTs34t6PEdwRuzZAQPN2IOPYNSvGNdJYryPacSeSNZ_z1xeBYXLOLQfOBZzyTReYDOhXdikhrNUbxjgnZQlSXBCVMlZ9PH42bHfp-LJIeJzW0yqnF6oLklvJP-fo8eW0k5iDOw'; - await expect(service.confirmUserAndInitPassword(token)).rejects.toEqual( + await expect( + service.confirmUserAndInitPassword(makeContext('trackingId'), token), + ).rejects.toEqual( new HttpException( makeErrorResponse('E009999'), HttpStatus.INTERNAL_SERVER_ERROR, ), ); }); +}); + +describe('UsersService.createUser', () => { + let source: DataSource = null; + beforeEach(async () => { + source = new DataSource({ + type: 'sqlite', + database: ':memory:', + logging: false, + entities: [__dirname + '/../../**/*.entity{.ts,.js}'], + synchronize: true, // trueにすると自動的にmigrationが行われるため注意 + }); + return source.initialize(); + }); + + afterEach(async () => { + await source.destroy(); + source = null; + }); + it('管理者権限のあるアクセストークンを使用して、新規ユーザが追加される(role:None)', async () => { - const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue(); - const adb2cParam = makeDefaultAdB2cMockValue(); - const sendgridMockValue = makeDefaultSendGridlValue(); - const configMockValue = makeDefaultConfigValue(); - const sortCriteriaRepositoryMockValue = - makeDefaultSortCriteriaRepositoryMockValue(); - const service = await makeUsersServiceMock( - usersRepositoryMockValue, - adb2cParam, - sendgridMockValue, - configMockValue, - sortCriteriaRepositoryMockValue, - ); + const module = await makeTestingModule(source); + const service = module.get(UsersService); + const adminExternalId = 'ADMIN0001'; + const { + accountId, + role: adminRole, + tier, + } = await createAccountAndAdminUser(source, adminExternalId); + + const token: AccessToken = { + userId: adminExternalId, + role: adminRole, + tier: tier, + }; + const name = 'test_user1'; const role = USER_ROLES.NONE; - const email = 'test1@example.co.jp'; + const email = 'test1@example.com'; const autoRenew = true; const licenseAlert = true; const notification = true; - const token: AccessToken = { userId: '0001', role: '', tier: 5 }; + + const externalId = '0001'; + + overrideAdB2cService(service, { + createUser: async ( + _context: Context, + _email: string, + _password: string, + _username: string, + ) => { + // ユーザー作成時に指定したパラメータが正しく渡されていることを確認 + expect(email).toEqual(_email); + expect(name).toEqual(_username); + + return { sub: externalId }; + }, + }); + overrideSendgridService(service, { + sendMail: async () => { + return; + }, + createMailContentFromEmailConfirmForNormalUser: async () => { + return { html: '', text: '', subject: '' }; + }, + }); + expect( await service.createUser( + makeContext('trackingId'), token, name, role, @@ -302,27 +435,45 @@ describe('UsersService.confirmUser', () => { notification, ), ).toEqual(undefined); - }); -}); -describe('UsersService.createUser', () => { + // 追加されたユーザーが正しくDBに登録されていることを確認 + const user = await getUserByExternalId(source, externalId); + expect(user).not.toBeNull(); + expect(user.account_id).toEqual(accountId); + expect(user.role).toEqual(role); + expect(user.author_id).toEqual(null); + expect(user.email_verified).toEqual(false); + expect(user.auto_renew).toEqual(autoRenew); + expect(user.license_alert).toEqual(licenseAlert); + expect(user.notification).toEqual(notification); + expect(user.encryption).toEqual(false); + expect(user.encryption_password).toEqual(null); + expect(user.prompt).toEqual(false); + + // 他にユーザーが登録されていないことを確認 + const users = await getUsers(source); + expect(users.length).toEqual(2); + }); + it('管理者権限のあるアクセストークンを使用して、新規ユーザが追加される(role:Author; 暗号化あり)', async () => { - const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue(); - const adb2cParam = makeDefaultAdB2cMockValue(); - const sendgridMockValue = makeDefaultSendGridlValue(); - const configMockValue = makeDefaultConfigValue(); - const sortCriteriaRepositoryMockValue = - makeDefaultSortCriteriaRepositoryMockValue(); - const service = await makeUsersServiceMock( - usersRepositoryMockValue, - adb2cParam, - sendgridMockValue, - configMockValue, - sortCriteriaRepositoryMockValue, - ); + const module = await makeTestingModule(source); + const service = module.get(UsersService); + const adminExternalId = 'ADMIN0001'; + const { + accountId, + role: adminRole, + tier, + } = await createAccountAndAdminUser(source, adminExternalId); + + const token: AccessToken = { + userId: adminExternalId, + role: adminRole, + tier: tier, + }; + const name = 'test_user2'; const role = USER_ROLES.AUTHOR; - const email = 'test2@example.co.jp'; + const email = 'test2@example.com'; const autoRenew = true; const licenseAlert = true; const notification = true; @@ -330,9 +481,35 @@ describe('UsersService.createUser', () => { const encryption = true; const prompt = true; const encryptionPassword = 'testPassword'; - const token: AccessToken = { userId: '0001', role: '', tier: 5 }; + + const externalId = '0001'; + + overrideAdB2cService(service, { + createUser: async ( + _context: Context, + _email: string, + _password: string, + _username: string, + ) => { + // ユーザー作成時に指定したパラメータが正しく渡されていることを確認 + expect(email).toEqual(_email); + expect(name).toEqual(_username); + + return { sub: externalId }; + }, + }); + overrideSendgridService(service, { + sendMail: async () => { + return; + }, + createMailContentFromEmailConfirmForNormalUser: async () => { + return { html: '', text: '', subject: '' }; + }, + }); + expect( await service.createUser( + makeContext('trackingId'), token, name, role, @@ -346,35 +523,694 @@ describe('UsersService.createUser', () => { prompt, ), ).toEqual(undefined); + + // 追加されたユーザーが正しくDBに登録されていることを確認 + const user = await getUserByExternalId(source, externalId); + expect(user).not.toBeNull(); + expect(user.account_id).toEqual(accountId); + expect(user.role).toEqual(role); + expect(user.author_id).toEqual(authorId); + expect(user.email_verified).toEqual(false); + expect(user.auto_renew).toEqual(autoRenew); + expect(user.license_alert).toEqual(licenseAlert); + expect(user.notification).toEqual(notification); + expect(user.encryption).toEqual(encryption); + expect(user.encryption_password).toEqual(encryptionPassword); + expect(user.prompt).toEqual(prompt); + + // 他にユーザーが登録されていないことを確認 + const users = await getUsers(source); + expect(users.length).toEqual(2); }); it('管理者権限のあるアクセストークンを使用して、新規ユーザが追加される(role:Author; 暗号化無し)', async () => { - const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue(); - const adb2cParam = makeDefaultAdB2cMockValue(); - const sendgridMockValue = makeDefaultSendGridlValue(); - const configMockValue = makeDefaultConfigValue(); - const sortCriteriaRepositoryMockValue = - makeDefaultSortCriteriaRepositoryMockValue(); - const service = await makeUsersServiceMock( - usersRepositoryMockValue, - adb2cParam, - sendgridMockValue, - configMockValue, - sortCriteriaRepositoryMockValue, - ); + const module = await makeTestingModule(source); + const service = module.get(UsersService); + const adminExternalId = 'ADMIN0001'; + const { + accountId, + role: adminRole, + tier, + } = await createAccountAndAdminUser(source, adminExternalId); + + const token: AccessToken = { + userId: adminExternalId, + role: adminRole, + tier: tier, + }; + const name = 'test_user2'; const role = USER_ROLES.AUTHOR; - const email = 'test2@example.co.jp'; + const email = 'test2@example.com'; const autoRenew = true; const licenseAlert = true; const notification = true; const authorId = 'testID'; const encryption = false; const prompt = true; - const encryptionPassword = undefined; - const token: AccessToken = { userId: '0001', role: '', tier: 5 }; + + const externalId = '0001'; + + overrideAdB2cService(service, { + createUser: async ( + _context: Context, + _email: string, + _password: string, + _username: string, + ) => { + // ユーザー作成時に指定したパラメータが正しく渡されていることを確認 + expect(email).toEqual(_email); + expect(name).toEqual(_username); + + return { sub: externalId }; + }, + }); + overrideSendgridService(service, { + sendMail: async () => { + return; + }, + createMailContentFromEmailConfirmForNormalUser: async () => { + return { html: '', text: '', subject: '' }; + }, + }); + expect( await service.createUser( + makeContext('trackingId'), + token, + name, + role, + email, + autoRenew, + licenseAlert, + notification, + authorId, + encryption, + undefined, + prompt, + ), + ).toEqual(undefined); + + // 追加されたユーザーが正しくDBに登録されていることを確認 + const user = await getUserByExternalId(source, externalId); + expect(user).not.toBeNull(); + expect(user.account_id).toEqual(accountId); + expect(user.role).toEqual(role); + expect(user.author_id).toEqual(authorId); + expect(user.email_verified).toEqual(false); + expect(user.auto_renew).toEqual(autoRenew); + expect(user.license_alert).toEqual(licenseAlert); + expect(user.notification).toEqual(notification); + expect(user.encryption).toEqual(encryption); + expect(user.encryption_password).toBeNull(); + expect(user.prompt).toEqual(prompt); + + // 他にユーザーが登録されていないことを確認 + const users = await getUsers(source); + expect(users.length).toEqual(2); + }); + + it('管理者権限のあるアクセストークンを使用して、新規ユーザが追加される(role:Transcriptioninst)', async () => { + const module = await makeTestingModule(source); + const service = module.get(UsersService); + const adminExternalId = 'ADMIN0001'; + const { + accountId, + role: adminRole, + tier, + } = await createAccountAndAdminUser(source, adminExternalId); + + const token: AccessToken = { + userId: adminExternalId, + role: adminRole, + tier: tier, + }; + + const name = 'test_user3'; + const role = USER_ROLES.TYPIST; + const email = 'test3@example.com'; + const autoRenew = true; + const licenseAlert = true; + const notification = true; + + const externalId = '0001'; + + overrideAdB2cService(service, { + createUser: async ( + _context: Context, + _email: string, + _password: string, + _username: string, + ) => { + // ユーザー作成時に指定したパラメータが正しく渡されていることを確認 + expect(email).toEqual(_email); + expect(name).toEqual(_username); + + return { sub: externalId }; + }, + }); + overrideSendgridService(service, { + sendMail: async () => { + return; + }, + createMailContentFromEmailConfirmForNormalUser: async () => { + return { html: '', text: '', subject: '' }; + }, + }); + + expect( + await service.createUser( + makeContext('trackingId'), + token, + name, + role, + email, + autoRenew, + licenseAlert, + notification, + ), + ).toEqual(undefined); + + // 追加されたユーザーが正しくDBに登録されていることを確認 + const user = await getUserByExternalId(source, externalId); + expect(user).not.toBeNull(); + expect(user.account_id).toEqual(accountId); + expect(user.role).toEqual(role); + expect(user.author_id).toBeNull(); + expect(user.email_verified).toEqual(false); + expect(user.auto_renew).toEqual(autoRenew); + expect(user.license_alert).toEqual(licenseAlert); + expect(user.notification).toEqual(notification); + expect(user.encryption).toEqual(false); + expect(user.encryption_password).toBeNull(); + expect(user.prompt).toEqual(false); + + // 他にユーザーが登録されていないことを確認 + const users = await getUsers(source); + expect(users.length).toEqual(2); + }); + + it('DBネットワークエラーとなる場合、リカバリ処理を実施し、ADB2Cに作成したユーザーを削除する', async () => { + const module = await makeTestingModule(source); + const service = module.get(UsersService); + const b2cService = module.get(AdB2cService); + const adminExternalId = 'ADMIN0001'; + const { role: adminRole, tier } = await createAccountAndAdminUser( + source, + adminExternalId, + ); + + const token: AccessToken = { + userId: adminExternalId, + role: adminRole, + tier: tier, + }; + + const name = 'test_user1'; + const role = USER_ROLES.NONE; + const email = 'test1@example.com'; + const autoRenew = true; + const licenseAlert = true; + const notification = true; + + const externalId = '0001'; + + overrideAdB2cService(service, { + createUser: async ( + _context: Context, + _email: string, + _password: string, + _username: string, + ) => { + // ユーザー作成時に指定したパラメータが正しく渡されていることを確認 + expect(email).toEqual(_email); + expect(name).toEqual(_username); + + return { sub: externalId }; + }, + deleteUser: jest.fn(), + }); + overrideSendgridService(service, { + sendMail: async () => { + return; + }, + createMailContentFromEmailConfirmForNormalUser: async () => { + return { html: '', text: '', subject: '' }; + }, + }); + + // DBエラーを発生させる + overrideUsersRepositoryService(service, { + createNormalUser: async () => { + throw new Error('DB error'); + }, + }); + + try { + await service.createUser( + makeContext('trackingId'), + token, + name, + role, + email, + autoRenew, + licenseAlert, + notification, + ); + } catch (e) { + if (e instanceof HttpException) { + expect(e.getStatus()).toEqual(HttpStatus.INTERNAL_SERVER_ERROR); + expect(e.getResponse()).toEqual(makeErrorResponse('E009999')); + } else { + fail(); + } + } + // ADB2Cに作成したユーザーを削除するメソッドが呼ばれていることを確認 + expect(b2cService.deleteUser).toBeCalledWith( + externalId, + makeContext('trackingId'), + ); + }); + + it('DBネットワークエラーとなる場合、リカバリ処理を実施されるが、そのリカバリ処理に失敗した場合、ADB2Cのユーザーは削除されない', async () => { + const module = await makeTestingModule(source); + const service = module.get(UsersService); + const b2cService = module.get(AdB2cService); + const adminExternalId = 'ADMIN0001'; + const { + accountId, + role: adminRole, + tier, + } = await createAccountAndAdminUser(source, adminExternalId); + + const token: AccessToken = { + userId: adminExternalId, + role: adminRole, + tier: tier, + }; + + const name = 'test_user1'; + const role = USER_ROLES.NONE; + const email = 'test1@example.com'; + const autoRenew = true; + const licenseAlert = true; + const notification = true; + + const externalId = '0001'; + + overrideAdB2cService(service, { + createUser: async ( + _context: Context, + _email: string, + _password: string, + _username: string, + ) => { + // ユーザー作成時に指定したパラメータが正しく渡されていることを確認 + expect(email).toEqual(_email); + expect(name).toEqual(_username); + + return { sub: externalId }; + }, + deleteUser: jest.fn().mockRejectedValue(new Error('ADB2C error')), + }); + overrideSendgridService(service, { + sendMail: async () => { + return; + }, + createMailContentFromEmailConfirmForNormalUser: async () => { + return { html: '', text: '', subject: '' }; + }, + }); + + // DBエラーを発生させる + overrideUsersRepositoryService(service, { + createNormalUser: async () => { + throw new Error('DB error'); + }, + }); + + try { + await service.createUser( + makeContext('trackingId'), + token, + name, + role, + email, + autoRenew, + licenseAlert, + notification, + ); + } catch (e) { + if (e instanceof HttpException) { + expect(e.getStatus()).toEqual(HttpStatus.INTERNAL_SERVER_ERROR); + expect(e.getResponse()).toEqual(makeErrorResponse('E009999')); + } else { + fail(); + } + } + // 新規ユーザーが登録されていないことを確認 + const users = await getUsers(source); + expect(users.length).toEqual(1); + //アカウントIDがテスト用の管理者ユーザーのものであることを確認 + expect(users[0].account_id).toEqual(accountId); + // ADB2Cに作成したユーザーを削除するメソッドが呼ばれていることを確認 + expect(b2cService.deleteUser).toBeCalledWith( + externalId, + makeContext('trackingId'), + ); + }); + + it('Azure ADB2Cでネットワークエラーとなる場合、エラーとなる。', async () => { + const module = await makeTestingModule(source); + const service = module.get(UsersService); + const adminExternalId = 'ADMIN0001'; + const { role: adminRole, tier } = await createAccountAndAdminUser( + source, + adminExternalId, + ); + + const token: AccessToken = { + userId: adminExternalId, + role: adminRole, + tier: tier, + }; + + const name = 'test_user1'; + const role = USER_ROLES.NONE; + const email = 'test1@example.com'; + const autoRenew = true; + const licenseAlert = true; + const notification = true; + + overrideAdB2cService(service, { + createUser: async ( + _context: Context, + _email: string, + _password: string, + _username: string, + ) => { + // ユーザー作成時に指定したパラメータが正しく渡されていることを確認 + expect(email).toEqual(_email); + expect(name).toEqual(_username); + + throw new Error('ADB2C error'); + }, + }); + overrideSendgridService(service, { + sendMail: async () => { + return; + }, + createMailContentFromEmailConfirmForNormalUser: async () => { + return { html: '', text: '', subject: '' }; + }, + }); + + try { + await service.createUser( + makeContext('trackingId'), + token, + name, + role, + email, + autoRenew, + licenseAlert, + notification, + ); + } catch (e) { + if (e instanceof HttpException) { + expect(e.getStatus()).toEqual(HttpStatus.INTERNAL_SERVER_ERROR); + expect(e.getResponse()).toEqual(makeErrorResponse('E009999')); + } else { + fail(); + } + } + + // ユーザーが登録されていないことを確認 + const users = await getUsers(source); + expect(users.length).toEqual(1); + }); + + it('Azure AD B2C内でメールアドレスが重複している場合、エラーとなる。', async () => { + const module = await makeTestingModule(source); + const service = module.get(UsersService); + const adminExternalId = 'ADMIN0001'; + const { role: adminRole, tier } = await createAccountAndAdminUser( + source, + adminExternalId, + ); + + const token: AccessToken = { + userId: adminExternalId, + role: adminRole, + tier: tier, + }; + + const name = 'test_user1'; + const role = USER_ROLES.NONE; + const email = 'test1@example.com'; + const autoRenew = true; + const licenseAlert = true; + const notification = true; + + overrideAdB2cService(service, { + createUser: async ( + _context: Context, + _email: string, + _password: string, + _username: string, + ) => { + // ユーザー作成時に指定したパラメータが正しく渡されていることを確認 + expect(email).toEqual(_email); + expect(name).toEqual(_username); + + // Conflictエラーを返す + return { + reason: 'email', + message: 'The email address is already in use by another account.', + }; + }, + }); + overrideSendgridService(service, { + sendMail: async () => { + return; + }, + createMailContentFromEmailConfirmForNormalUser: async () => { + return { html: '', text: '', subject: '' }; + }, + }); + + try { + await service.createUser( + makeContext('trackingId'), + token, + name, + role, + email, + autoRenew, + licenseAlert, + notification, + ); + } catch (e) { + if (e instanceof HttpException) { + expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST); + expect(e.getResponse()).toEqual(makeErrorResponse('E010301')); + } else { + fail(); + } + } + + // ユーザーが登録されていないことを確認 + const users = await getUsers(source); + expect(users.length).toEqual(1); + }); + + it('AuthorIDが重複している場合、エラーとなる。(AuthorID重複チェックでエラー)', async () => { + const module = await makeTestingModule(source); + const service = module.get(UsersService); + const adminExternalId = 'ADMIN0001'; + const { role: adminRole, tier } = await createAccountAndAdminUser( + source, + adminExternalId, + ); + + const token: AccessToken = { + userId: adminExternalId, + role: adminRole, + tier: tier, + }; + + const name = 'test_user2'; + const role = USER_ROLES.AUTHOR; + const autoRenew = true; + const licenseAlert = true; + const notification = true; + const authorId = 'testID'; + const encryption = true; + const prompt = true; + const encryptionPassword = 'testPassword'; + + const email_1 = 'test_1@example.com'; + const externalId_1 = '0001'; + + overrideAdB2cService(service, { + createUser: async ( + _context: Context, + _email: string, + _password: string, + _username: string, + ) => { + // ユーザー作成時に指定したパラメータが正しく渡されていることを確認 + expect(email_1).toEqual(_email); + expect(name).toEqual(_username); + + return { sub: externalId_1 }; + }, + }); + overrideSendgridService(service, { + sendMail: async () => { + return; + }, + createMailContentFromEmailConfirmForNormalUser: async () => { + return { html: '', text: '', subject: '' }; + }, + }); + + expect( + await service.createUser( + makeContext('trackingId'), + token, + name, + role, + email_1, + autoRenew, + licenseAlert, + notification, + authorId, + encryption, + encryptionPassword, + prompt, + ), + ).toEqual(undefined); + + { + // 他にユーザーが登録されていないことを確認 + const users = await getUsers(source); + expect(users.length).toEqual(2); + } + + // Azure Ad B2CのMockをユーザー2用に切り替える + const email_2 = 'test_1@example.com'; + const externalId_2 = '0001'; + overrideAdB2cService(service, { + createUser: async ( + _context: Context, + _email: string, + _password: string, + _username: string, + ) => { + // ユーザー作成時に指定したパラメータが正しく渡されていることを確認 + expect(email_2).toEqual(_email); + expect(name).toEqual(_username); + + return { sub: externalId_2 }; + }, + }); + + try { + await service.createUser( + makeContext('trackingId'), + token, + name, + role, + email_2, + autoRenew, + licenseAlert, + notification, + authorId, + encryption, + encryptionPassword, + prompt, + ); + } catch (e) { + if (e instanceof HttpException) { + expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST); + expect(e.getResponse()).toEqual(makeErrorResponse('E010302')); + } else { + fail(); + } + } + + // 新規にユーザーが登録されていないことを確認 + { + const users = await getUsers(source); + expect(users.length).toEqual(2); + } + }); + + it('AuthorIDが重複している場合、エラー(insert失敗)となり、リカバリ処理が実行され、ADB2Cに追加したユーザーが削除される', async () => { + const module = await makeTestingModule(source); + const service = module.get(UsersService); + const b2cService = module.get(AdB2cService); + const adminExternalId = 'ADMIN0001'; + const { + accountId, + role: adminRole, + tier, + } = await createAccountAndAdminUser(source, adminExternalId); + + const token: AccessToken = { + userId: adminExternalId, + role: adminRole, + tier: tier, + }; + + const name = 'test_user2'; + const role = USER_ROLES.AUTHOR; + const email = 'test2@example.com'; + const autoRenew = true; + const licenseAlert = true; + const notification = true; + const authorId = 'testID'; + const encryption = true; + const prompt = true; + const encryptionPassword = 'testPassword'; + + const externalId = '0001'; + + overrideAdB2cService(service, { + createUser: async ( + _context: Context, + _email: string, + _password: string, + _username: string, + ) => { + // ユーザー作成時に指定したパラメータが正しく渡されていることを確認 + expect(email).toEqual(_email); + expect(name).toEqual(_username); + + return { sub: externalId }; + }, + deleteUser: jest.fn(), + }); + overrideSendgridService(service, { + sendMail: async () => { + return; + }, + createMailContentFromEmailConfirmForNormalUser: async () => { + return { html: '', text: '', subject: '' }; + }, + }); + + // AuthorIDのUNIQUE制約エラーを発生させる + overrideUsersRepositoryService(service, { + createNormalUser: async () => { + throw { code: 'ER_DUP_ENTRY' }; + }, + }); + + try { + await service.createUser( + makeContext('trackingId'), token, name, role, @@ -386,33 +1222,80 @@ describe('UsersService.createUser', () => { encryption, encryptionPassword, prompt, - ), - ).toEqual(undefined); + ); + } catch (e) { + if (e instanceof HttpException) { + expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST); + expect(e.getResponse()).toEqual(makeErrorResponse('E010302')); + } else { + fail(); + } + } + // 新規にユーザーが登録されていないことを確認 + const users = await getUsers(source); + expect(users.length).toEqual(1); + expect(users[0].account_id).toEqual(accountId); + // ADB2Cに作成したユーザーを削除するメソッドが呼ばれていることを確認 + expect(b2cService.deleteUser).toBeCalledWith( + externalId, + makeContext('trackingId'), + ); }); - it('管理者権限のあるアクセストークンを使用して、新規ユーザが追加される(role:Transcriptioninst)', async () => { - const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue(); - const adb2cParam = makeDefaultAdB2cMockValue(); - const sendgridMockValue = makeDefaultSendGridlValue(); - const configMockValue = makeDefaultConfigValue(); - const sortCriteriaRepositoryMockValue = - makeDefaultSortCriteriaRepositoryMockValue(); - const service = await makeUsersServiceMock( - usersRepositoryMockValue, - adb2cParam, - sendgridMockValue, - configMockValue, - sortCriteriaRepositoryMockValue, - ); - const name = 'test_user3'; - const role = USER_ROLES.TYPIST; - const email = 'test3@example.co.jp'; + it('メール送信に失敗した場合、リカバリ処理が実行され、ADB2C,DBのユーザーが削除される', async () => { + const module = await makeTestingModule(source); + const service = module.get(UsersService); + const b2cService = module.get(AdB2cService); + + const adminExternalId = 'ADMIN0001'; + const { + accountId, + role: adminRole, + tier, + } = await createAccountAndAdminUser(source, adminExternalId); + + const token: AccessToken = { + userId: adminExternalId, + role: adminRole, + tier: tier, + }; + + const name = 'test_user1'; + const role = USER_ROLES.NONE; + const email = 'test1@example.com'; const autoRenew = true; const licenseAlert = true; const notification = true; - const token: AccessToken = { userId: '0001', role: '', tier: 5 }; - expect( + + const externalId = '0001'; + + overrideAdB2cService(service, { + createUser: async ( + _context: Context, + _email: string, + _password: string, + _username: string, + ) => { + // ユーザー作成時に指定したパラメータが正しく渡されていることを確認 + expect(email).toEqual(_email); + expect(name).toEqual(_username); + + return { sub: externalId }; + }, + deleteUser: jest.fn(), + }); + overrideSendgridService(service, { + sendMail: async () => { + throw new Error(); + }, + createMailContentFromEmailConfirmForNormalUser: async () => { + return { html: '', text: '', subject: '' }; + }, + }); + + try { await service.createUser( + makeContext('trackingId'), token, name, role, @@ -420,191 +1303,86 @@ describe('UsersService.createUser', () => { autoRenew, licenseAlert, notification, - undefined, - ), - ).toEqual(undefined); - }); - it('DBネットワークエラーとなる場合、エラーとなる。', async () => { - const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue(); - const adb2cParam = makeDefaultAdB2cMockValue(); - const sendgridMockValue = makeDefaultSendGridlValue(); - const configMockValue = makeDefaultConfigValue(); - const sortCriteriaRepositoryMockValue = - makeDefaultSortCriteriaRepositoryMockValue(); - usersRepositoryMockValue.createNormalUser = new Error('DB error'); - const service = await makeUsersServiceMock( - usersRepositoryMockValue, - adb2cParam, - sendgridMockValue, - configMockValue, - sortCriteriaRepositoryMockValue, - ); - const name = 'test_user5'; - const role = USER_ROLES.TYPIST; - const email = 'test5@example.co.jp'; - const autoRenew = true; - const licenseAlert = true; - const notification = true; - const token: AccessToken = { userId: '0001', role: '', tier: 5 }; - await expect( - service.createUser( - token, - name, - role, - email, - autoRenew, - licenseAlert, - notification, - ), - ).rejects.toEqual( - new HttpException( - makeErrorResponse('E009999'), - HttpStatus.INTERNAL_SERVER_ERROR, - ), - ); - }); - it('Azure ADB2Cでネットワークエラーとなる場合、エラーとなる。', async () => { - const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue(); - const adb2cParam = makeDefaultAdB2cMockValue(); - adb2cParam.createUser = new Error(); - const sendgridMockValue = makeDefaultSendGridlValue(); - const configMockValue = makeDefaultConfigValue(); - const sortCriteriaRepositoryMockValue = - makeDefaultSortCriteriaRepositoryMockValue(); - const service = await makeUsersServiceMock( - usersRepositoryMockValue, - adb2cParam, - sendgridMockValue, - configMockValue, - sortCriteriaRepositoryMockValue, - ); - const name = 'test_user6'; - const role = USER_ROLES.TYPIST; - const email = 'test6@example.co.jp'; - const autoRenew = true; - const licenseAlert = true; - const notification = true; - const token: AccessToken = { userId: '0001', role: '', tier: 5 }; - await expect( - service.createUser( - token, - name, - role, - email, - autoRenew, - licenseAlert, - notification, - ), - ).rejects.toEqual( - new HttpException( - makeErrorResponse('E009999'), - HttpStatus.INTERNAL_SERVER_ERROR, - ), - ); - }); - it('メールアドレスが重複している場合、エラーとなる。', async () => { - const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue(); - const adb2cParam = makeDefaultAdB2cMockValue(); - adb2cParam.createUser = { reason: 'email', message: 'ObjectConflict' }; - const sendgridMockValue = makeDefaultSendGridlValue(); - const configMockValue = makeDefaultConfigValue(); - const sortCriteriaRepositoryMockValue = - makeDefaultSortCriteriaRepositoryMockValue(); - const service = await makeUsersServiceMock( - usersRepositoryMockValue, - adb2cParam, - sendgridMockValue, - configMockValue, - sortCriteriaRepositoryMockValue, - ); - const name = 'test_user7'; - const role = USER_ROLES.TYPIST; - const email = 'test7@example.co.jp'; - const autoRenew = true; - const licenseAlert = true; - const notification = true; - const token: AccessToken = { userId: '0001', role: '', tier: 5 }; - await expect( - service.createUser( - token, - name, - role, - email, - autoRenew, - licenseAlert, - notification, - ), - ).rejects.toEqual( - new HttpException(makeErrorResponse('E010301'), HttpStatus.BAD_REQUEST), - ); - }); - it('AuthorIDが重複している場合、エラーとなる。(AuthorID重複チェックでエラー)', async () => { - const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue(); - const adb2cParam = makeDefaultAdB2cMockValue(); - const sendgridMockValue = makeDefaultSendGridlValue(); - const configMockValue = makeDefaultConfigValue(); - const sortCriteriaRepositoryMockValue = - makeDefaultSortCriteriaRepositoryMockValue(); - usersRepositoryMockValue.createNormalUser = new Error(); - usersRepositoryMockValue.existsAuthorId = true; + ); + } catch (e) { + if (e instanceof HttpException) { + expect(e.getStatus()).toEqual(HttpStatus.INTERNAL_SERVER_ERROR); + expect(e.getResponse()).toEqual(makeErrorResponse('E009999')); + } else { + fail(); + } + } - const service = await makeUsersServiceMock( - usersRepositoryMockValue, - adb2cParam, - sendgridMockValue, - configMockValue, - sortCriteriaRepositoryMockValue, - ); - const name = 'test_user8'; - const role = USER_ROLES.AUTHOR; - const email = 'test8@example.co.jp'; - const autoRenew = true; - const licenseAlert = true; - const notification = true; - const authorId = 'testID'; - const token: AccessToken = { userId: '0001', role: '', tier: 5 }; - await expect( - service.createUser( - token, - name, - role, - email, - autoRenew, - licenseAlert, - notification, - authorId, - ), - ).rejects.toEqual( - new HttpException(makeErrorResponse('E010302'), HttpStatus.BAD_REQUEST), + // 新規ユーザーが登録されていないことを確認 + const users = await getUsers(source); + expect(users.length).toEqual(1); + //アカウントIDがテスト用の管理者ユーザーのものであることを確認 + expect(users[0].account_id).toEqual(accountId); + // ADB2Cに作成したユーザーを削除するメソッドが呼ばれていることを確認 + expect(b2cService.deleteUser).toBeCalledWith( + externalId, + makeContext('trackingId'), ); }); - it('AuthorIDが重複している場合、エラーとなる。(insert失敗)', async () => { - const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue(); - const adb2cParam = makeDefaultAdB2cMockValue(); - const sendgridMockValue = makeDefaultSendGridlValue(); - const configMockValue = makeDefaultConfigValue(); - const sortCriteriaRepositoryMockValue = - makeDefaultSortCriteriaRepositoryMockValue(); - usersRepositoryMockValue.createNormalUser = new Error(); - usersRepositoryMockValue.createNormalUser.name = 'ER_DUP_ENTRY'; - const service = await makeUsersServiceMock( - usersRepositoryMockValue, - adb2cParam, - sendgridMockValue, - configMockValue, - sortCriteriaRepositoryMockValue, + it('メール送信に失敗した場合、リカバリ処理が実行されるが、そのリカバリ処理に失敗した場合、ADB2C,DBのユーザーが削除されない', async () => { + const module = await makeTestingModule(source); + const service = module.get(UsersService); + const b2cService = module.get(AdB2cService); + + const adminExternalId = 'ADMIN0001'; + const { role: adminRole, tier } = await createAccountAndAdminUser( + source, + adminExternalId, ); - const name = 'test_user9'; - const role = USER_ROLES.AUTHOR; - const email = 'test9@example.co.jp'; + + const token: AccessToken = { + userId: adminExternalId, + role: adminRole, + tier: tier, + }; + + const name = 'test_user1'; + const role = USER_ROLES.NONE; + const email = 'test1@example.com'; const autoRenew = true; const licenseAlert = true; const notification = true; - const authorId = 'testID'; - const token: AccessToken = { userId: '0001', role: '', tier: 5 }; - await expect( - service.createUser( + + const externalId = '0001'; + + overrideAdB2cService(service, { + createUser: async ( + _context: Context, + _email: string, + _password: string, + _username: string, + ) => { + // ユーザー作成時に指定したパラメータが正しく渡されていることを確認 + expect(email).toEqual(_email); + expect(name).toEqual(_username); + + return { sub: externalId }; + }, + deleteUser: jest.fn().mockRejectedValue(new Error()), + }); + overrideSendgridService(service, { + sendMail: async () => { + throw new Error(); + }, + createMailContentFromEmailConfirmForNormalUser: async () => { + return { html: '', text: '', subject: '' }; + }, + }); + overrideUsersRepositoryService(service, { + deleteNormalUser: async () => { + throw new Error(); + }, + }); + + try { + await service.createUser( + makeContext('trackingId'), token, name, role, @@ -612,10 +1390,23 @@ describe('UsersService.createUser', () => { autoRenew, licenseAlert, notification, - authorId, - ), - ).rejects.toEqual( - new HttpException(makeErrorResponse('E010302'), HttpStatus.BAD_REQUEST), + ); + } catch (e) { + if (e instanceof HttpException) { + expect(e.getStatus()).toEqual(HttpStatus.INTERNAL_SERVER_ERROR); + expect(e.getResponse()).toEqual(makeErrorResponse('E009999')); + } else { + fail(); + } + } + + // リカバリ処理が失敗したため、DBのユーザーが削除されないことを確認 + const users = await getUsers(source); + expect(users.length).toEqual(2); + // ADB2Cに作成したユーザーを削除するメソッドが呼ばれていることを確認 + expect(b2cService.deleteUser).toBeCalledWith( + externalId, + makeContext('trackingId'), ); }); }); @@ -882,6 +1673,7 @@ describe('UsersService.getUsers', () => { describe('UsersService.updateSortCriteria', () => { it('ソート条件を変更できる', async () => { const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue(); + const licensesRepositoryMockValue = null; const adb2cParam = makeDefaultAdB2cMockValue(); const sendgridMockValue = makeDefaultSendGridlValue(); const configMockValue = makeDefaultConfigValue(); @@ -889,6 +1681,7 @@ describe('UsersService.updateSortCriteria', () => { makeDefaultSortCriteriaRepositoryMockValue(); const service = await makeUsersServiceMock( usersRepositoryMockValue, + licensesRepositoryMockValue, adb2cParam, sendgridMockValue, configMockValue, @@ -906,6 +1699,7 @@ describe('UsersService.updateSortCriteria', () => { it('ユーザー情報が存在せず、ソート条件を変更できない', async () => { const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue(); + const licensesRepositoryMockValue = null; const adb2cParam = makeDefaultAdB2cMockValue(); const sendgridMockValue = makeDefaultSendGridlValue(); const configMockValue = makeDefaultConfigValue(); @@ -916,6 +1710,7 @@ describe('UsersService.updateSortCriteria', () => { const service = await makeUsersServiceMock( usersRepositoryMockValue, + licensesRepositoryMockValue, adb2cParam, sendgridMockValue, configMockValue, @@ -938,6 +1733,7 @@ describe('UsersService.updateSortCriteria', () => { it('ソート条件が存在せず、ソート条件を変更できない', async () => { const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue(); + const licensesRepositoryMockValue = null; const adb2cParam = makeDefaultAdB2cMockValue(); const sendgridMockValue = makeDefaultSendGridlValue(); const configMockValue = makeDefaultConfigValue(); @@ -949,6 +1745,7 @@ describe('UsersService.updateSortCriteria', () => { const service = await makeUsersServiceMock( usersRepositoryMockValue, + licensesRepositoryMockValue, adb2cParam, sendgridMockValue, configMockValue, @@ -973,6 +1770,7 @@ describe('UsersService.updateSortCriteria', () => { describe('UsersService.getSortCriteria', () => { it('ソート条件を取得できる', async () => { const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue(); + const licensesRepositoryMockValue = null; const adb2cParam = makeDefaultAdB2cMockValue(); const sendgridMockValue = makeDefaultSendGridlValue(); const configMockValue = makeDefaultConfigValue(); @@ -980,6 +1778,7 @@ describe('UsersService.getSortCriteria', () => { makeDefaultSortCriteriaRepositoryMockValue(); const service = await makeUsersServiceMock( usersRepositoryMockValue, + licensesRepositoryMockValue, adb2cParam, sendgridMockValue, configMockValue, @@ -997,6 +1796,7 @@ describe('UsersService.getSortCriteria', () => { it('ソート条件が存在せず、ソート条件を取得できない', async () => { const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue(); + const licensesRepositoryMockValue = null; const adb2cParam = makeDefaultAdB2cMockValue(); const sendgridMockValue = makeDefaultSendGridlValue(); const configMockValue = makeDefaultConfigValue(); @@ -1009,6 +1809,7 @@ describe('UsersService.getSortCriteria', () => { const service = await makeUsersServiceMock( usersRepositoryMockValue, + licensesRepositoryMockValue, adb2cParam, sendgridMockValue, configMockValue, @@ -1031,6 +1832,7 @@ describe('UsersService.getSortCriteria', () => { it('DBから取得した値が不正だった場合、エラーとなる', async () => { const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue(); + const licensesRepositoryMockValue = null; const adb2cParam = makeDefaultAdB2cMockValue(); const sendgridMockValue = makeDefaultSendGridlValue(); const configMockValue = makeDefaultConfigValue(); @@ -1045,6 +1847,7 @@ describe('UsersService.getSortCriteria', () => { const service = await makeUsersServiceMock( usersRepositoryMockValue, + licensesRepositoryMockValue, adb2cParam, sendgridMockValue, configMockValue, @@ -1568,7 +2371,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 146c416..6e9fa07 100644 --- a/dictation_server/src/features/users/users.service.ts +++ b/dictation_server/src/features/users/users.service.ts @@ -23,6 +23,7 @@ import { newUser, } from '../../repositories/users/entity/user.entity'; import { UsersRepositoryService } from '../../repositories/users/users.repository.service'; +import { LicensesRepositoryService } from '../../repositories/licenses/licenses.repository.service'; import { GetRelationsResponse, User } from './types/types'; import { AuthorIdAlreadyExistsError, @@ -39,11 +40,16 @@ import { import { DateWithZeroTime } from '../licenses/types/types'; import { Context } from '../../common/log'; import { UserRoles } from '../../common/types/role'; +import { + LicenseExpiredError, + LicenseUnavailableError, +} from '../../repositories/licenses/errors/types'; @Injectable() export class UsersService { constructor( private readonly usersRepository: UsersRepositoryService, + private readonly licensesRepository: LicensesRepositoryService, private readonly sortCriteriaRepository: SortCriteriaRepositoryService, private readonly adB2cService: AdB2cService, private readonly configService: ConfigService, @@ -74,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) { @@ -115,6 +123,7 @@ export class UsersService { * @returns void */ async createUser( + context: Context, accessToken: AccessToken, name: string, role: UserRoles, @@ -127,7 +136,7 @@ export class UsersService { encryptionPassword?: string | undefined, prompt?: boolean | undefined, ): Promise { - this.logger.log(`[IN] ${this.createUser.name}`); + this.logger.log(`[IN] [${context.trackingId}] ${this.createUser.name}`); //DBよりアクセス者の所属するアカウントIDを取得する let adminUser: EntityUser; @@ -176,6 +185,7 @@ export class UsersService { try { // idpにユーザーを作成 externalUser = await this.adB2cService.createUser( + context, email, ramdomPassword, name, @@ -219,6 +229,10 @@ export class UsersService { } catch (e) { this.logger.error(`error=${e}`); this.logger.error('create user failed'); + //リカバリー処理 + //Azure AD B2Cに登録したユーザー情報を削除する + await this.deleteB2cUser(externalUser.sub, context); + switch (e.code) { case 'ER_DUP_ENTRY': //AuthorID重複エラー @@ -248,11 +262,22 @@ export class UsersService { ); //SendGridAPIを呼び出してメールを送信する - await this.sendgridService.sendMail(email, from, subject, text, html); + await this.sendgridService.sendMail( + context, + email, + from, + subject, + text, + html, + ); } catch (e) { this.logger.error(`error=${e}`); this.logger.error('create user failed'); - this.logger.error(`[NOT IMPLEMENT] [RECOVER] delete user: ${newUser.id}`); + //リカバリー処理 + //Azure AD B2Cに登録したユーザー情報を削除する + await this.deleteB2cUser(externalUser.sub, context); + // DBからユーザーを削除する + await this.deleteUser(newUser.id, context); throw new HttpException( makeErrorResponse('E009999'), HttpStatus.INTERNAL_SERVER_ERROR, @@ -262,6 +287,35 @@ export class UsersService { return; } + // Azure AD B2Cに登録したユーザー情報を削除する + // TODO 「タスク 2452: リトライ処理を入れる箇所を検討し、実装する」の候補 + private async deleteB2cUser(externalUserId: string, context: Context) { + try { + await this.adB2cService.deleteUser(externalUserId, context); + this.logger.log( + `[${context.trackingId}] delete externalUser: ${externalUserId}`, + ); + } catch (error) { + this.logger.error(`error=${error}`); + this.logger.error( + `[MANUAL_RECOVERY_REQUIRED] [${context.trackingId}] Failed to delete externalUser: ${externalUserId}`, + ); + } + } + + // DBに登録したユーザー情報を削除する + private async deleteUser(userId: number, context: Context) { + try { + await this.usersRepository.deleteNormalUser(userId); + this.logger.log(`[${context.trackingId}] delete user: ${userId}`); + } catch (error) { + this.logger.error(`error=${error}`); + this.logger.error( + `[MANUAL_RECOVERY_REQUIRED] [${context.trackingId}] Failed to delete user: ${userId}`, + ); + } + } + // roleを受け取って、roleに応じたnewUserを作成して返却する private createNewUserInfo( role: UserRoles, @@ -313,8 +367,13 @@ export class UsersService { * confirm User And Init Password * @param token ユーザ仮登録時に払いだされるトークン */ - async confirmUserAndInitPassword(token: string): Promise { - this.logger.log(`[IN] ${this.confirmUserAndInitPassword.name}`); + async confirmUserAndInitPassword( + context: Context, + token: string, + ): Promise { + this.logger.log( + `[IN] [${context.trackingId}] ${this.confirmUserAndInitPassword.name}`, + ); const pubKey = getPublicKey(this.configService); @@ -351,7 +410,14 @@ export class UsersService { const html = `

    OMDS TOP PAGE URL.

    ${domains}"
    temporary password: ${ramdomPassword}`; // メールを送信 - await this.sendgridService.sendMail(email, from, subject, text, html); + await this.sendgridService.sendMail( + context, + email, + from, + subject, + text, + html, + ); } catch (e) { this.logger.error(`error=${e}`); if (e instanceof Error) { @@ -805,4 +871,51 @@ export class UsersService { this.logger.log(`[OUT] [${context.trackingId}] ${this.updateUser.name}`); } } + + /** + * ライセンスをユーザーに割り当てます + * @param context + * @param userId + * @param newLicenseId + */ + async allocateLicense( + context: Context, + userId: number, + newLicenseId: number, + ): Promise { + this.logger.log( + `[IN] [${context.trackingId}] ${this.allocateLicense.name} | params: { ` + + `userId: ${userId}, ` + + `newLicenseId: ${newLicenseId}, `, + ); + + try { + await this.licensesRepository.allocateLicense(userId, newLicenseId); + } catch (e) { + this.logger.error(`error=${e}`); + if (e instanceof Error) { + switch (e.constructor) { + case LicenseExpiredError: + throw new HttpException( + makeErrorResponse('E010805'), + HttpStatus.BAD_REQUEST, + ); + case LicenseUnavailableError: + throw new HttpException( + makeErrorResponse('E010806'), + HttpStatus.BAD_REQUEST, + ); + default: + throw new HttpException( + makeErrorResponse('E009999'), + HttpStatus.INTERNAL_SERVER_ERROR, + ); + } + } + } finally { + this.logger.log( + `[OUT] [${context.trackingId}] ${this.allocateLicense.name}`, + ); + } + } } diff --git a/dictation_server/src/gateways/adb2c/adb2c.service.ts b/dictation_server/src/gateways/adb2c/adb2c.service.ts index 82b0a4a..7d8c17b 100644 --- a/dictation_server/src/gateways/adb2c/adb2c.service.ts +++ b/dictation_server/src/gateways/adb2c/adb2c.service.ts @@ -56,11 +56,12 @@ export class AdB2cService { * @returns user */ async createUser( + context: Context, email: string, password: string, username: string, ): Promise<{ sub: string } | ConflictError> { - this.logger.log(`[IN] ${this.createUser.name}`); + this.logger.log(`[IN] [${context.trackingId}] ${this.createUser.name}`); try { // ユーザをADB2Cに登録 const newUser = await this.graphClient.api('users/').post({ @@ -93,7 +94,7 @@ export class AdB2cService { throw e; } finally { - this.logger.log(`[OUT] ${this.createUser.name}`); + this.logger.log(`[OUT] [${context.trackingId}] ${this.createUser.name}`); } } @@ -232,6 +233,26 @@ export class AdB2cService { this.logger.log(`[OUT] [${context.trackingId}] ${this.getUsers.name}`); } } + /** + * Azure AD B2Cからユーザ情報を削除する + * @param externalId 外部ユーザーID + * @param context コンテキスト + */ + async deleteUser(externalId: string, context: Context): Promise { + this.logger.log( + `[IN] [${context.trackingId}] ${this.deleteUser.name} | params: { externalId: ${externalId} };`, + ); + + try { + // https://learn.microsoft.com/en-us/graph/api/user-delete?view=graph-rest-1.0&tabs=javascript#example + await this.graphClient.api(`users/${externalId}`).delete(); + } catch (e) { + this.logger.error(`error=${e}`); + throw e; + } finally { + this.logger.log(`[OUT] [${context.trackingId}] ${this.deleteUser.name}`); + } + } } // TODO [Task2002] 文字列の配列を15要素ずつ区切る(この処理も別タスクで削除予定) diff --git a/dictation_server/src/gateways/blobstorage/blobstorage.service.ts b/dictation_server/src/gateways/blobstorage/blobstorage.service.ts index f5deda4..0c5d6af 100644 --- a/dictation_server/src/gateways/blobstorage/blobstorage.service.ts +++ b/dictation_server/src/gateways/blobstorage/blobstorage.service.ts @@ -51,13 +51,22 @@ export class BlobstorageService { this.sharedKeyCredentialEU, ); } + /** * Creates container - * @param companyName + * @param context + * @param accountId + * @param country * @returns container */ - async createContainer(accountId: number, country: string): Promise { - this.logger.log(`[IN] ${this.createContainer.name}`); + async createContainer( + context: Context, + accountId: number, + country: string, + ): Promise { + this.logger.log( + `[IN] [${context.trackingId}] ${this.createContainer.name}`, + ); // 国に応じたリージョンでコンテナ名を指定してClientを取得 const containerClient = this.getContainerClient(accountId, country); @@ -69,9 +78,54 @@ export class BlobstorageService { this.logger.error(`error=${e}`); throw e; } finally { - this.logger.log(`[OUT] ${this.createContainer.name}`); + this.logger.log( + `[OUT] [${context.trackingId}] ${this.createContainer.name}`, + ); } } + + /** + * 指定されたコンテナを削除します。(コンテナが存在しない場合、何もせず終了します) + * @param context + * @param accountId + * @param country + */ + async deleteContainer( + context: Context, + accountId: number, + country: string, + ): Promise { + this.logger.log( + `[IN] [${context.trackingId}] ${this.deleteContainer.name}`, + ); + + try { + // 国に応じたリージョンでコンテナ名を指定してClientを取得 + const containerClient = this.getContainerClient(accountId, country); + const { succeeded, errorCode, date } = + await containerClient.deleteIfExists(); + this.logger.log( + `succeeded: ${succeeded}, errorCode: ${errorCode}, date: ${date}`, + ); + + // 失敗時、コンテナが存在しない場合以外はエラーとして例外をスローする + // コンテナ不在の場合のエラーコードは「ContainerNotFound」以下を参照 + // https://learn.microsoft.com/ja-jp/rest/api/storageservices/blob-service-error-codes + if (!succeeded && errorCode !== 'ContainerNotFound') { + throw new Error( + `delete blob container failed. succeeded: ${succeeded}, errorCode: ${errorCode}, date: ${date}`, + ); + } + } catch (e) { + this.logger.error(`error=${e}`); + throw e; + } finally { + this.logger.log( + `[OUT] [${context.trackingId}] ${this.deleteContainer.name}`, + ); + } + } + /** * Containers exists * @param country diff --git a/dictation_server/src/gateways/sendgrid/sendgrid.service.ts b/dictation_server/src/gateways/sendgrid/sendgrid.service.ts index 12d864e..3fb3e66 100644 --- a/dictation_server/src/gateways/sendgrid/sendgrid.service.ts +++ b/dictation_server/src/gateways/sendgrid/sendgrid.service.ts @@ -3,6 +3,7 @@ import { ConfigService } from '@nestjs/config'; import { sign } from '../../common/jwt'; import sendgrid from '@sendgrid/mail'; import { getPrivateKey } from '../../common/jwt/jwt'; +import { Context } from '../../common/log'; @Injectable() export class SendGridService { @@ -20,10 +21,15 @@ export class SendGridService { * @returns メールのサブジェクトとコンテンツ */ async createMailContentFromEmailConfirm( + context: Context, accountId: number, userId: number, email: string, ): Promise<{ subject: string; text: string; html: string }> { + this.logger.log( + `[IN] [${context.trackingId}] ${this.createMailContentFromEmailConfirm.name}`, + ); + const lifetime = this.configService.get('EMAIL_CONFIRM_LIFETIME') ?? 0; const privateKey = getPrivateKey(this.configService); @@ -39,6 +45,9 @@ export class SendGridService { const domains = this.configService.get('APP_DOMAIN'); const path = 'mail-confirm/'; + this.logger.log( + `[OUT] [${context.trackingId}] ${this.createMailContentFromEmailConfirm.name}`, + ); return { subject: 'Verify your new account', text: `The verification URL. ${domains}${path}?verify=${token}`, @@ -85,17 +94,23 @@ export class SendGridService { /** * メールを送信する - * @param accountId アカウントID - * @param userId ユーザーID - * @returns user confirm token + * @param context + * @param to + * @param from + * @param subject + * @param text + * @param html + * @returns mail */ async sendMail( + context: Context, to: string, from: string, subject: string, text: string, html: string, ): Promise { + this.logger.log(`[IN] [${context.trackingId}] ${this.sendMail.name}`); try { const res = await sendgrid .send({ @@ -114,8 +129,10 @@ export class SendGridService { `status code: ${res.statusCode} body: ${JSON.stringify(res.body)}`, ); } catch (e) { - console.log(JSON.stringify(e)); + this.logger.error(e); throw e; + } finally { + this.logger.log(`[OUT] [${context.trackingId}] ${this.sendMail.name}`); } } } diff --git a/dictation_server/src/repositories/accounts/accounts.repository.service.ts b/dictation_server/src/repositories/accounts/accounts.repository.service.ts index 2aabfff..e58669a 100644 --- a/dictation_server/src/repositories/accounts/accounts.repository.service.ts +++ b/dictation_server/src/repositories/accounts/accounts.repository.service.ts @@ -79,7 +79,7 @@ export class AccountsRepositoryService { } /** - * プライマリ管理者とアカウントを同時に作成する + * プライマリ管理者とアカウント、ソート条件を同時に作成する * @param companyName * @param country * @param dealerAccountId @@ -92,7 +92,7 @@ export class AccountsRepositoryService { async createAccount( companyName: string, country: string, - dealerAccountId: number | null, + dealerAccountId: number | undefined, tier: number, adminExternalUserId: string, adminUserRole: string, @@ -150,6 +150,27 @@ export class AccountsRepositoryService { }); } + /** + * プライマリ管理者とアカウント、ソート条件を同時に削除する + * @param accountId + * @returns delete + */ + async deleteAccount(accountId: number, userId: number): Promise { + await this.dataSource.transaction(async (entityManager) => { + const accountsRepo = entityManager.getRepository(Account); + const usersRepo = entityManager.getRepository(User); + const sortCriteriaRepo = entityManager.getRepository(SortCriteria); + // ソート条件を削除 + await sortCriteriaRepo.delete({ + user_id: userId, + }); + // プライマリ管理者を削除 + await usersRepo.delete({ id: userId }); + // アカウントを削除 + await accountsRepo.delete({ id: accountId }); + }); + } + /** * アカウントIDからアカウント情報を取得する * @param id @@ -429,6 +450,7 @@ export class AccountsRepositoryService { async getPartnerLicense( id: number, currentDate: Date, + expiringSoonDate: Date, offset: number, limit: number, ): Promise<{ @@ -486,6 +508,24 @@ export class AccountsRepositoryService { entityManager, ); + // 第五の不足数を算出するためのライセンス数情報を取得する + let expiringSoonLicense: number; + let allocatableLicenseWithMargin: number; + if (childAccount.tier === TIERS.TIER5) { + expiringSoonLicense = await this.getExpiringSoonLicense( + entityManager, + childAccount.id, + currentDate, + expiringSoonDate, + ); + allocatableLicenseWithMargin = + await this.getAllocatableLicenseWithMargin( + entityManager, + childAccount.id, + expiringSoonDate, + ); + } + // 戻り値用の値を設定 const childPartnerLicenseFromRepository: PartnerLicenseInfoForRepository = { @@ -495,6 +535,8 @@ export class AccountsRepositoryService { stockLicense: childLicenseOrderStatus.stockLicense, issuedRequested: childLicenseOrderStatus.issuedRequested, issueRequesting: childLicenseOrderStatus.issueRequesting, + expiringSoonLicense: expiringSoonLicense, + allocatableLicenseWithMargin: allocatableLicenseWithMargin, }; childPartnerLicensesFromRepository.push( @@ -517,42 +559,6 @@ export class AccountsRepositoryService { }); } - /** - * 不足数を算出するためのライセンス数情報を取得する - * @param id - * @param currentDate - * @param expiringSoonDate - * @returns expiringSoonLicense - * @returns expiringSoonDate - */ - async getLicenseCountForShortage( - id: number, - currentDate: Date, - expiringSoonDate: Date, - ): Promise<{ - expiringSoonLicense: number; - allocatableLicenseWithMargin: number; - }> { - return await this.dataSource.transaction(async (entityManager) => { - const expiringSoonLicense = await this.getExpiringSoonLicense( - entityManager, - id, - currentDate, - expiringSoonDate, - ); - const allocatableLicenseWithMargin = - await this.getAllocatableLicenseWithMargin( - entityManager, - id, - expiringSoonDate, - ); - return { - expiringSoonLicense: expiringSoonLicense, - allocatableLicenseWithMargin: allocatableLicenseWithMargin, - }; - }); - } - /** * Dealer(Tier4)アカウント情報を取得する * @returns dealer accounts diff --git a/dictation_server/src/repositories/accounts/entity/account.entity.ts b/dictation_server/src/repositories/accounts/entity/account.entity.ts index 82d57ea..ad65437 100644 --- a/dictation_server/src/repositories/accounts/entity/account.entity.ts +++ b/dictation_server/src/repositories/accounts/entity/account.entity.ts @@ -22,16 +22,16 @@ export class Account { @Column() country: string; - @Column() + @Column({ default: false }) delegation_permission: boolean; - @Column() + @Column({ default: false }) locked: boolean; @Column() company_name: string; - @Column() + @Column({ default: false }) verified: boolean; @Column({ nullable: true }) @@ -43,16 +43,16 @@ export class Account { @Column({ nullable: true }) deleted_at?: Date; - @Column() - created_by: string; + @Column({ nullable: true }) + created_by?: string; - @CreateDateColumn() + @CreateDateColumn({ default: () => "datetime('now', 'localtime')" }) // defaultはSQLite用設定値.本番用は別途migrationで設定 created_at: Date; - @Column() - updated_by: string; + @Column({ nullable: true }) + updated_by?: string; - @UpdateDateColumn() + @UpdateDateColumn({ default: () => "datetime('now', 'localtime')" }) // defaultはSQLite用設定値.本番用は別途migrationで設定 updated_at: Date; @OneToMany(() => User, (user) => user.id) diff --git a/dictation_server/src/repositories/licenses/entity/license.entity.ts b/dictation_server/src/repositories/licenses/entity/license.entity.ts index 301b0ff..3d3df06 100644 --- a/dictation_server/src/repositories/licenses/entity/license.entity.ts +++ b/dictation_server/src/repositories/licenses/entity/license.entity.ts @@ -6,6 +6,7 @@ import { UpdateDateColumn, OneToOne, JoinColumn, + ManyToOne, } from 'typeorm'; import { User } from '../../users/entity/user.entity'; @@ -164,3 +165,43 @@ export class CardLicense { @UpdateDateColumn({}) updated_at: Date; } + +@Entity({ name: 'license_allocation_history' }) +export class LicenseAllocationHistory { + @PrimaryGeneratedColumn() + id: number; + + @Column() + user_id: number; + + @Column() + license_id: number; + + @Column() + is_allocated: boolean; + + @Column() + executed_at: Date; + + @Column() + switch_from_type: string; + + @Column({ nullable: true }) + deleted_at: Date; + + @Column({ nullable: true }) + created_by: string; + + @CreateDateColumn() + created_at: Date; + + @Column({ nullable: true }) + updated_by: string; + + @UpdateDateColumn() + updated_at: Date; + + @ManyToOne(() => License, (licenses) => licenses.id) + @JoinColumn({ name: 'license_id' }) + license?: License; +} diff --git a/dictation_server/src/repositories/licenses/errors/types.ts b/dictation_server/src/repositories/licenses/errors/types.ts index 972f850..e0f9fbe 100644 --- a/dictation_server/src/repositories/licenses/errors/types.ts +++ b/dictation_server/src/repositories/licenses/errors/types.ts @@ -6,3 +6,15 @@ export class LicenseNotExistError extends Error {} // 取り込むライセンスが既に取り込み済みのエラー export class LicenseKeyAlreadyActivatedError extends Error {} + +// 注文不在エラー +export class OrderNotFoundError extends Error {} +// 注文発行済エラー +export class AlreadyIssuedError extends Error {} +// ライセンス不足エラー +export class LicensesShortageError extends Error {} + +// ライセンス有効期限切れエラー +export class LicenseExpiredError extends Error {} +// ライセンス割り当て不可エラー +export class LicenseUnavailableError extends Error {} diff --git a/dictation_server/src/repositories/licenses/licenses.repository.module.ts b/dictation_server/src/repositories/licenses/licenses.repository.module.ts index a142c1f..252f01b 100644 --- a/dictation_server/src/repositories/licenses/licenses.repository.module.ts +++ b/dictation_server/src/repositories/licenses/licenses.repository.module.ts @@ -5,6 +5,7 @@ import { CardLicenseIssue, License, LicenseOrder, + LicenseAllocationHistory, } from './entity/license.entity'; import { LicensesRepositoryService } from './licenses.repository.service'; @@ -15,6 +16,7 @@ import { LicensesRepositoryService } from './licenses.repository.service'; License, CardLicense, CardLicenseIssue, + LicenseAllocationHistory, ]), ], providers: [LicensesRepositoryService], diff --git a/dictation_server/src/repositories/licenses/licenses.repository.service.ts b/dictation_server/src/repositories/licenses/licenses.repository.service.ts index 1d085be..5bd59b9 100644 --- a/dictation_server/src/repositories/licenses/licenses.repository.service.ts +++ b/dictation_server/src/repositories/licenses/licenses.repository.service.ts @@ -1,10 +1,11 @@ import { Injectable, Logger } from '@nestjs/common'; -import { DataSource, In } from 'typeorm'; +import { DataSource, In, IsNull, MoreThanOrEqual } from 'typeorm'; import { LicenseOrder, License, CardLicenseIssue, CardLicense, + LicenseAllocationHistory, } from './entity/license.entity'; import { CARD_LICENSE_LENGTH, @@ -12,12 +13,24 @@ import { LICENSE_STATUS_ISSUE_REQUESTING, LICENSE_STATUS_ISSUED, LICENSE_TYPE, + SWITCH_FROM_TYPE, + TIERS, } from '../../constants'; import { PoNumberAlreadyExistError, LicenseNotExistError, LicenseKeyAlreadyActivatedError, + LicensesShortageError, + AlreadyIssuedError, + OrderNotFoundError, + LicenseExpiredError, + LicenseUnavailableError, } from './errors/types'; +import { + AllocatableLicenseInfo, + DateWithZeroTime, +} from '../../features/licenses/types/types'; +import { NewAllocatedLicenseExpirationDate } from '../../features/licenses/types/types'; @Injectable() export class LicensesRepositoryService { @@ -90,6 +103,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(); @@ -146,6 +160,7 @@ export class LicensesRepositoryService { } const cardLicenses = []; + //TODO タスク 2409: カードライセンスのレコード作成がbulkinsertになっていない // カードライセンステーブルを作成する(BULK INSERT) for (let i = 0; i < count; i++) { const cardLicense = new CardLicense(); @@ -296,4 +311,234 @@ export class LicensesRepositoryService { }; }); } + + /** + * 対象の注文を発行する + * @context Context + * @param orderedAccountId + * @param myAccountId + * @param tier + * @param poNumber + */ + async issueLicense( + orderedAccountId: number, + myAccountId: number, + tier: number, + poNumber: string, + ): Promise { + const nowDate = new Date(); + await this.dataSource.transaction(async (entityManager) => { + const licenseOrderRepo = entityManager.getRepository(LicenseOrder); + const licenseRepo = entityManager.getRepository(License); + + const issuingOrder = await licenseOrderRepo.findOne({ + where: { + from_account_id: orderedAccountId, + po_number: poNumber, + }, + }); + // 注文が存在しない場合、エラー + if (!issuingOrder) { + throw new OrderNotFoundError(`No order found for PONumber:${poNumber}`); + } + // 既に発行済みの注文の場合、エラー + if (issuingOrder.status !== LICENSE_STATUS_ISSUE_REQUESTING) { + throw new AlreadyIssuedError( + `An order for PONumber:${poNumber} has already been issued.`, + ); + } + + // ライセンステーブルのレコードを作成する + const newLicenses = Array.from({ length: issuingOrder.quantity }, () => { + const license = new License(); + license.account_id = orderedAccountId; + license.status = LICENSE_ALLOCATED_STATUS.UNALLOCATED; + license.type = LICENSE_TYPE.NORMAL; + license.order_id = issuingOrder.id; + return license; + }); + // ライセンス注文テーブルを更新(注文元) + await licenseOrderRepo.update( + { id: issuingOrder.id }, + { + issued_at: nowDate, + status: LICENSE_STATUS_ISSUED, + }, + ); + // ライセンステーブルを登録(注文元) + await licenseRepo.save(newLicenses); + + // 第一階層の場合はストックライセンスの概念が存在しないため、ストックライセンス変更処理は行わない + if (tier !== TIERS.TIER1) { + const licensesToUpdate = await licenseRepo.find({ + where: { + account_id: myAccountId, + status: LICENSE_ALLOCATED_STATUS.UNALLOCATED, + type: LICENSE_TYPE.NORMAL, + }, + order: { + id: 'ASC', + }, + take: newLicenses.length, + }); + + // 登録したライセンスに対して自身のライセンスが不足していた場合、エラー + if (newLicenses.length > licensesToUpdate.length) { + throw new LicensesShortageError( + `Shortage Licenses.Number of licenses attempted to be issued is ${newLicenses.length}.`, + ); + } + for (const licenseToUpdate of licensesToUpdate) { + licenseToUpdate.status = LICENSE_ALLOCATED_STATUS.DELETED; + licenseToUpdate.deleted_at = nowDate; + licenseToUpdate.delete_order_id = issuingOrder.id; + } + // 自身のライセンスを削除(論理削除)する + await licenseRepo.save(licensesToUpdate); + } + }); + } + /** + * 対象のアカウントの割り当て可能なライセンスを取得する + * @context Context + * @param accountId + * @param tier + * @return AllocatableLicenseInfo[] + */ + async getAllocatableLicenses( + myAccountId: number, + ): Promise { + const nowDate = new DateWithZeroTime(); + const licenseRepo = this.dataSource.getRepository(License); + const queryBuilder = licenseRepo + .createQueryBuilder('license') + .where('license.account_id = :accountId', { accountId: myAccountId }) + .andWhere('license.status IN (:...statuses)', { + statuses: [ + LICENSE_ALLOCATED_STATUS.UNALLOCATED, + LICENSE_ALLOCATED_STATUS.REUSABLE, + ], + }) + .andWhere( + '(license.expiry_date >= :nowDate OR license.expiry_date IS NULL)', + { nowDate }, + ) + .orderBy('license.expiry_date IS NULL', 'DESC') + .addOrderBy('license.expiry_date', 'DESC') + .addOrderBy('license.id', 'ASC'); + const allocatableLicenses = await queryBuilder.getMany(); + return allocatableLicenses.map((license) => ({ + licenseId: license.id, + expiryDate: license.expiry_date, + })); + } + /** + * ライセンスをユーザーに割り当てる + * @param userId + * @param newLicenseId + */ + async allocateLicense(userId: number, newLicenseId: number): Promise { + await this.dataSource.transaction(async (entityManager) => { + const licenseRepo = entityManager.getRepository(License); + const licenseAllocationHistoryRepo = entityManager.getRepository( + LicenseAllocationHistory, + ); + // 割り当て対象のライセンス情報を取得 + const targetLicense = await licenseRepo.findOne({ + where: { + id: newLicenseId, + }, + }); + + // 期限切れの場合はエラー + if (targetLicense.expiry_date) { + const currentDay = new Date(); + currentDay.setHours(23, 59, 59, 999); + if (targetLicense.expiry_date < currentDay) { + throw new LicenseExpiredError( + `License is expired. expiration date: ${targetLicense.expiry_date} current Date: ${currentDay}`, + ); + } + } + // ライセンス状態が「未割当」「再利用可能」以外の場合はエラー + if ( + targetLicense.status === LICENSE_ALLOCATED_STATUS.ALLOCATED || + targetLicense.status === LICENSE_ALLOCATED_STATUS.DELETED + ) { + throw new LicenseUnavailableError( + `License is unavailable. License status: ${targetLicense.status}`, + ); + } + + // 対象ユーザーのライセンス割り当て状態を取得 + const allocatedLicense = await licenseRepo.findOne({ + where: { + allocated_user_id: userId, + }, + }); + + // 既にライセンスが割り当てられているなら、割り当てを解除 + if (allocatedLicense) { + allocatedLicense.status = LICENSE_ALLOCATED_STATUS.REUSABLE; + allocatedLicense.allocated_user_id = null; + + await licenseRepo.save(allocatedLicense); + + // ライセンス割り当て履歴テーブルへ登録 + const deallocationHistory = new LicenseAllocationHistory(); + deallocationHistory.user_id = userId; + deallocationHistory.license_id = allocatedLicense.id; + deallocationHistory.is_allocated = false; + deallocationHistory.executed_at = new Date(); + deallocationHistory.switch_from_type = SWITCH_FROM_TYPE.NONE; + await licenseAllocationHistoryRepo.save(deallocationHistory); + } + + // ライセンス割り当てを実施 + targetLicense.status = LICENSE_ALLOCATED_STATUS.ALLOCATED; + targetLicense.allocated_user_id = userId; + // 有効期限が未設定なら365日後に設定 + if (!targetLicense.expiry_date) { + targetLicense.expiry_date = new NewAllocatedLicenseExpirationDate(); + } + await licenseRepo.save(targetLicense); + + // 直近割り当てたライセンス種別を取得 + const oldLicenseType = await licenseAllocationHistoryRepo.findOne({ + relations: { + license: true, + }, + where: { user_id: userId, is_allocated: true }, + order: { executed_at: 'DESC' }, + }); + + let switchFromType = ''; + if (oldLicenseType) { + switch (oldLicenseType.license.type) { + case LICENSE_TYPE.CARD: + switchFromType = SWITCH_FROM_TYPE.CARD; + break; + case LICENSE_TYPE.TRIAL: + switchFromType = SWITCH_FROM_TYPE.TRIAL; + break; + default: + switchFromType = SWITCH_FROM_TYPE.NONE; + break; + } + } else { + switchFromType = SWITCH_FROM_TYPE.NONE; + } + + // ライセンス割り当て履歴テーブルへ登録 + const allocationHistory = new LicenseAllocationHistory(); + allocationHistory.user_id = userId; + allocationHistory.license_id = targetLicense.id; + allocationHistory.is_allocated = true; + allocationHistory.executed_at = new Date(); + // TODO switchFromTypeの値については「PBI1234: 第一階層として、ライセンス数推移情報をCSV出力したい」で正式対応 + allocationHistory.switch_from_type = switchFromType; + + await licenseAllocationHistoryRepo.save(allocationHistory); + }); + } } diff --git a/dictation_server/src/repositories/users/entity/user.entity.ts b/dictation_server/src/repositories/users/entity/user.entity.ts index 1e01643..51cc19c 100644 --- a/dictation_server/src/repositories/users/entity/user.entity.ts +++ b/dictation_server/src/repositories/users/entity/user.entity.ts @@ -33,40 +33,40 @@ export class User { @Column({ nullable: true }) accepted_terms_version?: string; - @Column() + @Column({ default: false }) email_verified: boolean; - @Column() + @Column({ default: true }) auto_renew: boolean; - @Column() + @Column({ default: true }) license_alert: boolean; - @Column() + @Column({ default: true }) notification: boolean; - @Column({ nullable: true }) + @Column({ default: false }) encryption?: boolean; @Column({ nullable: true }) encryption_password?: string; - @Column({ nullable: true }) + @Column({ default: false }) prompt?: boolean; @Column({ nullable: true }) deleted_at?: Date; - @Column() + @Column({ nullable: true }) created_by: string; - @CreateDateColumn() + @CreateDateColumn({ default: () => "datetime('now', 'localtime')" }) // defaultはSQLite用設定値.本番用は別途migrationで設定 created_at: Date; - @Column() - updated_by: string; + @Column({ nullable: true }) + updated_by?: string; - @UpdateDateColumn() + @UpdateDateColumn({ default: () => "datetime('now', 'localtime')" }) // defaultはSQLite用設定値.本番用は別途migrationで設定 updated_at: Date; @ManyToOne(() => Account, (account) => account.user) diff --git a/dictation_server/src/repositories/users/users.repository.service.ts b/dictation_server/src/repositories/users/users.repository.service.ts index 97a7417..7683de3 100644 --- a/dictation_server/src/repositories/users/users.repository.service.ts +++ b/dictation_server/src/repositories/users/users.repository.service.ts @@ -13,37 +13,19 @@ import { InvalidRoleChangeError, EncryptionPasswordNeedError, } from './errors/types'; -import { USER_ROLES } from '../../constants'; +import { + LICENSE_ALLOCATED_STATUS, + LICENSE_TYPE, + TRIAL_LICENSE_ISSUE_NUM, + USER_ROLES, +} from '../../constants'; +import { License } from '../licenses/entity/license.entity'; +import { NewTrialLicenseExpirationDate } from '../../features/licenses/types/types'; @Injectable() export class UsersRepositoryService { constructor(private dataSource: DataSource) {} - async create( - accountId: number, - externalUserId: string, - role: string, - acceptedTermsVersion: string, - ): Promise { - const user = new User(); - { - user.account_id = accountId; - user.external_id = externalUserId; - user.role = role; - user.accepted_terms_version = acceptedTermsVersion; - } - - const createdEntity = await this.dataSource.transaction( - async (entityManager) => { - const repo = entityManager.getRepository(User); - const newUser = repo.create(user); - const persisted = await repo.save(newUser); - return persisted; - }, - ); - return createdEntity; - } - /** * 一般ユーザーを作成する * @param user @@ -285,6 +267,68 @@ 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[] = []; + + // トライアルライセンスの有効期限は今日を起算日として30日後の日付が変わるまで + const expiryDate = new NewTrialLicenseExpirationDate(); + + 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 @@ -337,4 +381,22 @@ export class UsersRepositoryService { return typists; }); } + + /** + * UserID指定のユーザーとソート条件を同時に削除する + * @param userId + * @returns delete + */ + async deleteNormalUser(userId: number): Promise { + await this.dataSource.transaction(async (entityManager) => { + const usersRepo = entityManager.getRepository(User); + const sortCriteriaRepo = entityManager.getRepository(SortCriteria); + // ソート条件を削除 + await sortCriteriaRepo.delete({ + user_id: userId, + }); + // プライマリ管理者を削除 + await usersRepo.delete({ id: userId }); + }); + } }