Merged PR 85: IF実装(ユーザー情報取得API/音声ファイルアップロード完了API)

## 概要
[Task1644: IF実装(ユーザー情報取得API/音声ファイルアップロード完了API)](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/1644)

- 以下の外部連携APIのIFを実装しました。
  - ユーザー情報取得API
  - 音声ファイルアップロード完了API

## レビューポイント
- 音声ファイルアップロード完了APIについてTaskフォルダを掘って新規に追加したがフォルダ構成に問題はないか。
- IFの応答ステータスは適切か。
- リクエスト/レスポンスは想定通りか
  - ユーザー情報取得API応答のWorkTypeID周りが不安なのでご確認をお願いします。

## UIの変更
- なし

## 動作確認状況
- Swaggerをローカルで確認
This commit is contained in:
makabe.t 2023-04-24 09:58:25 +00:00
parent d2d95c6b02
commit 8a0815821e
10 changed files with 806 additions and 81 deletions

View File

@ -6,7 +6,11 @@
"operationId": "checkHealth",
"summary": "",
"parameters": [],
"responses": { "200": { "description": "" } }
"responses": {
"200": {
"description": ""
}
}
}
},
"/auth/token": {
@ -18,7 +22,9 @@
"required": true,
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/TokenRequest" }
"schema": {
"$ref": "#/components/schemas/TokenRequest"
}
}
}
},
@ -27,7 +33,9 @@
"description": "成功時のレスポンス",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/TokenResponse" }
"schema": {
"$ref": "#/components/schemas/TokenResponse"
}
}
}
},
@ -35,7 +43,9 @@
"description": "認証エラー",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/ErrorResponse" }
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
},
@ -43,7 +53,9 @@
"description": "想定外のサーバーエラー",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/ErrorResponse" }
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
}
@ -61,7 +73,9 @@
"description": "成功時のレスポンス",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/AccessTokenResponse" }
"schema": {
"$ref": "#/components/schemas/AccessTokenResponse"
}
}
}
},
@ -69,7 +83,9 @@
"description": "認証エラー",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/ErrorResponse" }
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
},
@ -77,13 +93,19 @@
"description": "想定外のサーバーエラー",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/ErrorResponse" }
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
}
},
"tags": ["auth"],
"security": [{ "bearer": [] }]
"security": [
{
"bearer": []
}
]
}
},
"/accounts": {
@ -95,7 +117,9 @@
"required": true,
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/CreateAccountRequest" }
"schema": {
"$ref": "#/components/schemas/CreateAccountRequest"
}
}
}
},
@ -114,7 +138,9 @@
"description": "登録済みユーザーからの登録など",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/ErrorResponse" }
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
},
@ -122,7 +148,9 @@
"description": "想定外のサーバーエラー",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/ErrorResponse" }
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
}
@ -130,6 +158,56 @@
"tags": ["accounts"]
}
},
"/files/audio/upload-finished": {
"post": {
"operationId": "createTask",
"summary": "",
"parameters": [],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/AudioUploadFinishedRequest"
}
}
}
},
"responses": {
"200": {
"description": "成功時のレスポンス",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/AudioUploadFinishedResponse"
}
}
}
},
"400": {
"description": "不正なパラメータ",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
},
"500": {
"description": "想定外のサーバーエラー",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
}
},
"tags": ["files"]
}
},
"/users/confirm": {
"post": {
"operationId": "confirmUser",
@ -139,7 +217,9 @@
"required": true,
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/ConfirmRequest" }
"schema": {
"$ref": "#/components/schemas/ConfirmRequest"
}
}
}
},
@ -148,7 +228,9 @@
"description": "成功時のレスポンス",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/ConfirmResponse" }
"schema": {
"$ref": "#/components/schemas/ConfirmResponse"
}
}
}
},
@ -156,7 +238,9 @@
"description": "不正なトークン",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/ErrorResponse" }
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
},
@ -164,7 +248,9 @@
"description": "想定外のサーバーエラー",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/ErrorResponse" }
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
}
@ -181,7 +267,9 @@
"required": true,
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/ConfirmRequest" }
"schema": {
"$ref": "#/components/schemas/ConfirmRequest"
}
}
}
},
@ -190,7 +278,9 @@
"description": "成功時のレスポンス",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/ConfirmResponse" }
"schema": {
"$ref": "#/components/schemas/ConfirmResponse"
}
}
}
},
@ -198,7 +288,9 @@
"description": "不正なトークン",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/ErrorResponse" }
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
},
@ -206,7 +298,9 @@
"description": "想定外のサーバーエラー",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/ErrorResponse" }
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
}
@ -224,7 +318,9 @@
"description": "成功時のレスポンス",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/GetUsersResponse" }
"schema": {
"$ref": "#/components/schemas/GetUsersResponse"
}
}
}
},
@ -232,7 +328,9 @@
"description": "認証エラー",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/ErrorResponse" }
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
},
@ -240,13 +338,19 @@
"description": "想定外のサーバーエラー",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/ErrorResponse" }
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
}
},
"tags": ["users"],
"security": [{ "bearer": [] }]
"security": [
{
"bearer": []
}
]
}
},
"/users/signup": {
@ -258,7 +362,9 @@
"required": true,
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/SignupRequest" }
"schema": {
"$ref": "#/components/schemas/SignupRequest"
}
}
}
},
@ -267,7 +373,9 @@
"description": "成功時のレスポンス",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/SignupResponse" }
"schema": {
"$ref": "#/components/schemas/SignupResponse"
}
}
}
},
@ -275,7 +383,9 @@
"description": "登録済みメールによる再登録、AuthorIDの重複など",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/ErrorResponse" }
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
},
@ -283,7 +393,9 @@
"description": "認証エラー",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/ErrorResponse" }
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
},
@ -291,13 +403,64 @@
"description": "想定外のサーバーエラー",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/ErrorResponse" }
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
}
},
"tags": ["users"],
"security": [{ "bearer": [] }]
"security": [
{
"bearer": []
}
]
}
},
"/users/user-info": {
"get": {
"operationId": "getUserInfo",
"summary": "",
"parameters": [],
"responses": {
"200": {
"description": "成功時のレスポンス",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/GetUserInfoResponse"
}
}
}
},
"401": {
"description": "認証エラー",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
},
"500": {
"description": "想定外のサーバーエラー",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
}
},
"tags": ["users"],
"security": [
{
"bearer": []
}
]
}
},
"/notification/register": {
@ -309,7 +472,9 @@
"required": true,
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/RegisterRequest" }
"schema": {
"$ref": "#/components/schemas/RegisterRequest"
}
}
}
},
@ -318,7 +483,9 @@
"description": "成功時のレスポンス",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/RegisterResponse" }
"schema": {
"$ref": "#/components/schemas/RegisterResponse"
}
}
}
},
@ -326,7 +493,9 @@
"description": "不正なパラメータ",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/ErrorResponse" }
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
},
@ -334,7 +503,9 @@
"description": "認証エラー",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/ErrorResponse" }
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
},
@ -342,13 +513,19 @@
"description": "想定外のサーバーエラー",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/ErrorResponse" }
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
}
},
"tags": ["notification"],
"security": [{ "bearer": [] }]
"security": [
{
"bearer": []
}
]
}
},
"/files/audio/upload-location": {
@ -371,7 +548,9 @@
"description": "認証エラー",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/ErrorResponse" }
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
},
@ -379,13 +558,19 @@
"description": "想定外のサーバーエラー",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/ErrorResponse" }
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
}
},
"tags": ["files"],
"security": [{ "bearer": [] }]
"security": [
{
"bearer": []
}
]
}
},
"/files/audio/download-location": {
@ -398,7 +583,9 @@
"required": true,
"in": "query",
"description": "音声ファイル情報をDBから取得するためのID",
"schema": { "type": "string" }
"schema": {
"type": "string"
}
}
],
"responses": {
@ -416,7 +603,9 @@
"description": "認証エラー",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/ErrorResponse" }
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
},
@ -424,13 +613,19 @@
"description": "想定外のサーバーエラー",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/ErrorResponse" }
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
}
},
"tags": ["files"],
"security": [{ "bearer": [] }]
"security": [
{
"bearer": []
}
]
}
}
},
@ -455,7 +650,9 @@
"TokenRequest": {
"type": "object",
"properties": {
"idToken": { "type": "string" },
"idToken": {
"type": "string"
},
"type": {
"type": "string",
"description": "web or mobile or desktop"
@ -466,43 +663,69 @@
"TokenResponse": {
"type": "object",
"properties": {
"refreshToken": { "type": "string" },
"accessToken": { "type": "string" }
"refreshToken": {
"type": "string"
},
"accessToken": {
"type": "string"
}
},
"required": ["refreshToken", "accessToken"]
},
"ErrorResponse": {
"type": "object",
"properties": {
"message": { "type": "string" },
"code": { "type": "string" }
"message": {
"type": "string"
},
"code": {
"type": "string"
}
},
"required": ["message", "code"]
},
"AccessTokenResponse": {
"type": "object",
"properties": { "accessToken": { "type": "string" } },
"properties": {
"accessToken": {
"type": "string"
}
},
"required": ["accessToken"]
},
"CreateAccountRequest": {
"type": "object",
"properties": {
"companyName": { "type": "string" },
"companyName": {
"type": "string"
},
"country": {
"type": "string",
"description": "国名(ISO 3166-1 alpha-2)",
"minLength": 2,
"maxLength": 2
},
"dealerAccountId": { "type": "number", "nullable": true },
"adminName": { "type": "string" },
"adminMail": { "type": "string" },
"adminPassword": { "type": "string" },
"dealerAccountId": {
"type": "number",
"nullable": true
},
"adminName": {
"type": "string"
},
"adminMail": {
"type": "string"
},
"adminPassword": {
"type": "string"
},
"acceptedTermsVersion": {
"type": "string",
"description": "同意済み利用規約のバージョン"
},
"token": { "type": "string", "description": "reCAPTCHA Token" }
"token": {
"type": "string",
"description": "reCAPTCHA Token"
}
},
"required": [
"companyName",
@ -515,25 +738,146 @@
"token"
]
},
"CreateAccountResponse": { "type": "object", "properties": {} },
"CreateAccountResponse": {
"type": "object",
"properties": {}
},
"AudioUploadFinishedRequest": {
"type": "object",
"properties": {
"url": {
"type": "string",
"description": "アップロード先Blob Storage(ファイル名含む)"
},
"authorId": {
"type": "string",
"description": "自分自身(ログイン認証)したAuthorID"
},
"fileName": {
"type": "string",
"description": "音声ファイル名"
},
"duration": {
"type": "string",
"description": "音声ファイルの録音時間yyyy-mm-ddThh:mm:ss.sss"
},
"createdDate": {
"type": "string",
"description": "音声ファイルの録音作成日時(開始日時)yyyy-mm-ddThh:mm:ss.sss"
},
"completedDate": {
"type": "string",
"description": "音声ファイルの録音作成終了日時yyyy-mm-ddThh:mm:ss.sss"
},
"uploadedDate": {
"type": "string",
"description": "音声ファイルのアップロード日時yyyy-mm-ddThh:mm:ss.sss"
},
"fileSize": {
"type": "string"
},
"priority": {
"type": "string",
"description": "優先度 \"00\":Normal / \"01\":High"
},
"audioFormat": {
"type": "string",
"description": "録音形式: DSS/DS2(SP)/DS2(QP)"
},
"comment": {
"type": "string"
},
"workType": {
"type": "string"
},
"optionItemLabel": {
"type": "string",
"minLength": 1,
"maxLength": 16
},
"optionItemValue": {
"type": "string",
"minLength": 1,
"maxLength": 20
},
"isEncrypted": {
"type": "boolean"
}
},
"required": [
"url",
"authorId",
"fileName",
"duration",
"createdDate",
"completedDate",
"uploadedDate",
"fileSize",
"priority",
"audioFormat",
"comment",
"workType",
"optionItemLabel",
"optionItemValue",
"isEncrypted"
]
},
"AudioUploadFinishedResponse": {
"type": "object",
"properties": {
"jobNumber": {
"type": "string",
"description": "8桁固定の数字"
}
},
"required": ["jobNumber"]
},
"ConfirmRequest": {
"type": "object",
"properties": { "token": { "type": "string" } },
"properties": {
"token": {
"type": "string"
}
},
"required": ["token"]
},
"ConfirmResponse": { "type": "object", "properties": {} },
"ConfirmResponse": {
"type": "object",
"properties": {}
},
"User": {
"type": "object",
"properties": {
"name": { "type": "string" },
"role": { "type": "string", "description": "none/author/typist" },
"authorId": { "type": "string", "nullable": true },
"typistGroupName": { "type": "string", "nullable": true },
"email": { "type": "string" },
"emailVerified": { "type": "boolean" },
"autoRenew": { "type": "boolean" },
"licenseAlert": { "type": "boolean" },
"notification": { "type": "boolean" }
"name": {
"type": "string"
},
"role": {
"type": "string",
"description": "none/author/typist"
},
"authorId": {
"type": "string",
"nullable": true
},
"typistGroupName": {
"type": "string",
"nullable": true
},
"email": {
"type": "string"
},
"emailVerified": {
"type": "boolean"
},
"autoRenew": {
"type": "boolean"
},
"licenseAlert": {
"type": "boolean"
},
"notification": {
"type": "boolean"
}
},
"required": [
"name",
@ -552,7 +896,9 @@
"properties": {
"users": {
"type": "array",
"items": { "$ref": "#/components/schemas/User" }
"items": {
"$ref": "#/components/schemas/User"
}
}
},
"required": ["users"]
@ -560,14 +906,31 @@
"SignupRequest": {
"type": "object",
"properties": {
"name": { "type": "string" },
"role": { "type": "string", "description": "none/author/typist" },
"authorId": { "type": "string" },
"typistGroupId": { "type": "number" },
"email": { "type": "string" },
"autoRenew": { "type": "boolean" },
"licenseAlert": { "type": "boolean" },
"notification": { "type": "boolean" }
"name": {
"type": "string"
},
"role": {
"type": "string",
"description": "none/author/typist"
},
"authorId": {
"type": "string"
},
"typistGroupId": {
"type": "number"
},
"email": {
"type": "string"
},
"autoRenew": {
"type": "boolean"
},
"licenseAlert": {
"type": "boolean"
},
"notification": {
"type": "boolean"
}
},
"required": [
"name",
@ -578,11 +941,111 @@
"notification"
]
},
"SignupResponse": { "type": "object", "properties": {} },
"SignupResponse": {
"type": "object",
"properties": {}
},
"OptionItem": {
"type": "object",
"properties": {
"label": {
"type": "string",
"minLength": 1,
"maxLength": 16,
"description": "Option Itemのラベル"
},
"initialValueType": {
"type": "number",
"description": "項目タイプ 1:Blank/2:Default/3:前の値"
},
"defaultValue": {
"type": "string",
"minLength": 1,
"maxLength": 20,
"description": "typeでDefaultを選択した場合のデフォルト値"
}
},
"required": ["label", "initialValueType", "defaultValue"]
},
"OptionItemList": {
"type": "object",
"properties": {
"workTypeId": {
"type": "string"
},
"optionItemList": {
"maxItems": 10,
"description": "1WorkTypeIDにつき、10個まで登録可能",
"type": "array",
"items": {
"$ref": "#/components/schemas/OptionItem"
}
}
},
"required": ["workTypeId", "optionItemList"]
},
"GetUserInfoResponse": {
"type": "object",
"properties": {
"authorId": {
"type": "string",
"description": "自分自身(ログイン認証)したAuthorID"
},
"authorIdList": {
"description": "属しているアカウントのAuthorID List(全て)",
"type": "array",
"items": {
"type": "string"
}
},
"workTypeList": {
"maxItems": 20,
"description": "Authorに設定されているWorktypeIDのリスト最大20個",
"type": "array",
"items": {
"$ref": "#/components/schemas/OptionItemList"
}
},
"isEncrypted": {
"type": "boolean",
"description": "音声ファイルを暗号化するかどうか"
},
"encryptionPassword": {
"type": "string",
"description": "Encryptionで暗号化を掛ける場合のパスワード",
"nullable": true
},
"activeWorktype": {
"type": "string",
"description": "デフォルトで利用するWorkTypeIDアカウントに紐づくWorkTypeIDから一つ指定"
},
"audioFormat": {
"type": "string",
"description": "録音形式: DSS/DS2(SP)/DS2(QP) DS2固定"
},
"prompt": {
"type": "boolean",
"description": "デバイス上で、Option Itemを表示するかどうか"
}
},
"required": [
"authorId",
"authorIdList",
"workTypeList",
"isEncrypted",
"encryptionPassword",
"activeWorktype",
"audioFormat",
"prompt"
]
},
"RegisterRequest": {
"type": "object",
"properties": {
"pns": { "type": "string", "description": "wns or apns" },
"pns": {
"type": "string",
"description": "wns or apns"
},
"handler": {
"type": "string",
"description": "wnsのチャネルURI or apnsのデバイストークン"
@ -590,15 +1053,26 @@
},
"required": ["pns", "handler"]
},
"RegisterResponse": { "type": "object", "properties": {} },
"RegisterResponse": {
"type": "object",
"properties": {}
},
"AudioUploadLocationResponse": {
"type": "object",
"properties": { "url": { "type": "string" } },
"properties": {
"url": {
"type": "string"
}
},
"required": ["url"]
},
"AudioDownloadLocationResponse": {
"type": "object",
"properties": { "url": { "type": "string" } },
"properties": {
"url": {
"type": "string"
}
},
"required": ["url"]
}
}

View File

@ -23,6 +23,9 @@ import { NotificationhubModule } from './gateways/notificationhub/notificationhu
import { NotificationhubService } from './gateways/notificationhub/notificationhub.service';
import { NotificationModule } from './features/notification/notification.module';
import { BlobModule } from './features/blob/blob.module';
import { TaskController } from './features/task/task.controller';
import { TaskService } from './features/task/task.service';
import { TaskModule } from './features/task/task.module';
@Module({
imports: [
@ -37,6 +40,7 @@ import { BlobModule } from './features/blob/blob.module';
CryptoModule,
AdB2cModule,
AccountsModule,
TaskModule,
UsersModule,
SendGridModule,
AccountsRepositoryModule,
@ -63,11 +67,13 @@ import { BlobModule } from './features/blob/blob.module';
HealthController,
AuthController,
AccountsController,
TaskController,
UsersController,
],
providers: [
AuthService,
AccountsService,
TaskService,
UsersService,
NotificationhubService,
],

View File

@ -0,0 +1,24 @@
import { Test, TestingModule } from '@nestjs/testing';
import { TaskController } from './task.controller';
import { TaskService } from './task.service';
describe('TaskController', () => {
let controller: TaskController;
const mockTaskervice = {};
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [TaskController],
providers: [TaskService],
})
.overrideProvider(TaskService)
.useValue(mockTaskervice)
.compile();
controller = module.get<TaskController>(TaskController);
});
it('should be defined', () => {
expect(controller).toBeDefined();
});
});

View File

@ -0,0 +1,38 @@
import { Body, Controller, HttpStatus, Post } from '@nestjs/common';
import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
import { ErrorResponse } from '../../common/error/types/types';
import { TaskService } from './task.service';
import {
AudioUploadFinishedRequest,
AudioUploadFinishedResponse,
} from './types/types';
@ApiTags('files')
@Controller('files')
export class TaskController {
constructor(private readonly taskService: TaskService) {}
@ApiResponse({
status: HttpStatus.OK,
type: AudioUploadFinishedResponse,
description: '成功時のレスポンス',
})
@ApiResponse({
status: HttpStatus.BAD_REQUEST,
description: '不正なパラメータ',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: '想定外のサーバーエラー',
type: ErrorResponse,
})
@ApiOperation({ operationId: 'createTask' })
@Post('audio/upload-finished')
async uploadFinished(
@Body() body: AudioUploadFinishedRequest,
): Promise<AudioUploadFinishedResponse> {
console.log(body);
return { jobNumber: '00000001' };
}
}

View File

@ -0,0 +1,10 @@
import { Module } from '@nestjs/common';
import { TaskController } from './task.controller';
import { TaskService } from './task.service';
@Module({
imports: [],
controllers: [TaskController],
providers: [TaskService],
})
export class TaskModule {}

View File

@ -0,0 +1,21 @@
import { Test, TestingModule } from '@nestjs/testing';
import { TaskService } from './task.service';
describe('TaskService', () => {
let service: TaskService;
const mockTaskService = {};
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [TaskService],
})
.overrideProvider(TaskService)
.useValue(mockTaskService)
.compile();
service = module.get<TaskService>(TaskService);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
});

View File

@ -0,0 +1,4 @@
import { Injectable } from '@nestjs/common';
@Injectable()
export class TaskService {}

View File

@ -0,0 +1,48 @@
import { ApiProperty } from '@nestjs/swagger';
export class AudioUploadFinishedRequest {
@ApiProperty({ description: 'アップロード先Blob Storage(ファイル名含む)' })
url: string;
@ApiProperty({ description: '自分自身(ログイン認証)したAuthorID' })
authorId: string;
@ApiProperty({ description: '音声ファイル名' })
fileName: string;
@ApiProperty({
description: '音声ファイルの録音時間yyyy-mm-ddThh:mm:ss.sss',
})
duration: string;
@ApiProperty({
description:
'音声ファイルの録音作成日時(開始日時)yyyy-mm-ddThh:mm:ss.sss',
})
createdDate: string;
@ApiProperty({
description: '音声ファイルの録音作成終了日時yyyy-mm-ddThh:mm:ss.sss',
})
completedDate: string;
@ApiProperty({
description: '音声ファイルのアップロード日時yyyy-mm-ddThh:mm:ss.sss',
})
uploadedDate: string;
@ApiProperty()
fileSize: string;
@ApiProperty({ description: '優先度 "00":Normal / "01":High' })
priority: string;
@ApiProperty({ description: '録音形式: DSS/DS2(SP)/DS2(QP)' })
audioFormat: string;
@ApiProperty()
comment: string;
@ApiProperty()
workType: string;
@ApiProperty({ minLength: 1, maxLength: 16 })
optionItemLabel: string;
@ApiProperty({ minLength: 1, maxLength: 20 })
optionItemValue: string;
@ApiProperty()
isEncrypted: boolean;
}
export class AudioUploadFinishedResponse {
@ApiProperty({ description: '8桁固定の数字' })
jobNumber: string;
}

View File

@ -68,3 +68,59 @@ export class SignupRequest {
}
export class SignupResponse {}
export class OptionItem {
@ApiProperty({
minLength: 1,
maxLength: 16,
description: 'Option Itemのラベル',
})
label: string;
@ApiProperty({ description: '項目タイプ 1:Blank/2:Default/3:前の値' })
initialValueType: number;
@ApiProperty({
minLength: 1,
maxLength: 20,
description: 'typeでDefaultを選択した場合のデフォルト値',
})
defaultValue: string;
}
export class OptionItemList {
@ApiProperty()
workTypeId: string;
@ApiProperty({
type: [OptionItem],
maxItems: 10,
description: '1WorkTypeIDにつき、10個まで登録可能',
})
optionItemList: OptionItem[];
}
export class GetUserInfoResponse {
@ApiProperty({ description: '自分自身(ログイン認証)したAuthorID' })
authorId: string;
@ApiProperty({ description: '属しているアカウントのAuthorID List(全て)' })
authorIdList: string[];
@ApiProperty({
type: [OptionItemList],
maxItems: 20,
description: 'Authorに設定されているWorktypeIDのリスト最大20個',
})
workTypeList: OptionItemList[];
@ApiProperty({ description: '音声ファイルを暗号化するかどうか' })
isEncrypted: boolean;
@ApiProperty({
description: 'Encryptionで暗号化を掛ける場合のパスワード',
nullable: true,
})
encryptionPassword?: string | undefined;
@ApiProperty({
description:
'デフォルトで利用するWorkTypeIDアカウントに紐づくWorkTypeIDから一つ指定',
})
activeWorktype: string;
@ApiProperty({ description: '録音形式: DSS/DS2(SP)/DS2(QP) DS2固定' })
audioFormat: string;
@ApiProperty({ description: 'デバイス上で、Option Itemを表示するかどうか' })
prompt: boolean;
}

View File

@ -9,6 +9,7 @@ import { ErrorResponse } from '../../common/error/types/types';
import {
ConfirmRequest,
ConfirmResponse,
GetUserInfoResponse,
GetUsersResponse,
SignupRequest,
SignupResponse,
@ -121,4 +122,47 @@ export class UsersController {
console.log(body);
return {};
}
@ApiResponse({
status: HttpStatus.OK,
type: GetUserInfoResponse,
description: '成功時のレスポンス',
})
@ApiResponse({
status: HttpStatus.UNAUTHORIZED,
description: '認証エラー',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: '想定外のサーバーエラー',
type: ErrorResponse,
})
@ApiOperation({ operationId: 'getUserInfo' })
@ApiBearerAuth()
@Get('user-info')
async getUserInfo(@Req() req: Request): Promise<GetUserInfoResponse> {
console.log(req.header('Authorization'));
return {
authorId: 'AUTHOR',
authorIdList: ['AUTHOR', 'AUTHOR1'],
workTypeList: [
{
workTypeId: '1',
optionItemList: [
{
label: '1',
initialValueType: 0,
defaultValue: 'default',
},
],
},
],
isEncrypted: true,
encryptionPassword: '',
activeWorktype: '',
audioFormat: 'DS2',
prompt: true,
};
}
}