Merged PR 97: API I/F実装(ライセンス注文登録API)

## 概要
[Task1681: API I/F実装(ライセンス注文登録API)](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/1681)

- 元PBIへのリンク(内容・目的などはそちらにあるはず)
 [プロダクト バックログ項目 1221: ライセンスを注文したい](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/OMDSDictation/_workitems/edit/1221)

- 何をどう変更したか、追加したライブラリなど
 ラフスケッチに基づき、ライセンス注文登録APIのI/F実装とopenapi化を行いました。

- このPull Requestでの対象/対象外
 変更分すべてが対象になります

- 影響範囲(他の機能にも影響があるか)
 無し

## レビューポイント
- Swagger UI上でテスト実行すると、正常時のレスポンスコードが200ではなく201となります。
湯本さんが実施されたユーザ追加のAPI I/F実装の動画を見ると、その時も201となっていたので、そのまま進めましたが、もし問題ある場合は指摘お願いします。

## UIの変更
- 無し

## 動作確認状況
- ローカルでSwagger確認

## 補足
- 相談、参考資料などがあれば
This commit is contained in:
masaaki 2023-05-12 01:00:10 +00:00
parent 3f16e84317
commit 21695a6590
8 changed files with 202 additions and 0 deletions

View File

@ -1218,6 +1218,71 @@
} }
] ]
} }
},
"/licenses/orders": {
"post": {
"operationId": "createOrders",
"summary": "",
"parameters": [],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreateOrdersRequest"
}
}
}
},
"responses": {
"200": {
"description": "成功時のレスポンス",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreateOrdersResponse"
}
}
}
},
"400": {
"description": "同一PONumberの注文がすでに存在する場合など",
"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": ["licenses"],
"security": [
{
"bearer": []
}
]
}
} }
}, },
"info": { "info": {
@ -1867,6 +1932,22 @@
"RegisterResponse": { "RegisterResponse": {
"type": "object", "type": "object",
"properties": {} "properties": {}
},
"CreateOrdersRequest": {
"type": "object",
"properties": {
"poNumber": {
"type": "string"
},
"orderCount": {
"type": "number"
}
},
"required": ["poNumber", "orderCount"]
},
"CreateOrdersResponse": {
"type": "object",
"properties": {}
} }
} }
} }

View File

@ -28,6 +28,9 @@ import { FilesService } from './features/files/files.service';
import { TasksService } from './features/tasks/tasks.service'; import { TasksService } from './features/tasks/tasks.service';
import { TasksController } from './features/tasks/tasks.controller'; import { TasksController } from './features/tasks/tasks.controller';
import { TasksModule } from './features/tasks/tasks.module'; import { TasksModule } from './features/tasks/tasks.module';
import { LicensesModule } from './features/licenses/licenses.module';
import { LicensesService } from './features/licenses/licenses.service';
import { LicensesController } from './features/licenses/licenses.controller';
@Module({ @Module({
imports: [ imports: [
@ -65,6 +68,7 @@ import { TasksModule } from './features/tasks/tasks.module';
}), }),
NotificationModule, NotificationModule,
NotificationhubModule, NotificationhubModule,
LicensesModule,
], ],
controllers: [ controllers: [
HealthController, HealthController,
@ -74,6 +78,7 @@ import { TasksModule } from './features/tasks/tasks.module';
FilesController, FilesController,
TasksController, TasksController,
UsersController, UsersController,
LicensesController,
], ],
providers: [ providers: [
AuthService, AuthService,
@ -82,6 +87,7 @@ import { TasksModule } from './features/tasks/tasks.module';
NotificationhubService, NotificationhubService,
FilesService, FilesService,
TasksService, TasksService,
LicensesService,
], ],
}) })
export class AppModule { export class AppModule {

View File

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

View File

@ -0,0 +1,49 @@
import { Body, Controller, HttpStatus, Post, Req } from '@nestjs/common';
import {
ApiResponse,
ApiTags,
ApiOperation,
ApiBearerAuth,
} from '@nestjs/swagger';
import { ErrorResponse } from '../../common/error/types/types';
import { LicensesService } from './licenses.service';
import { CreateOrdersResponse, CreateOrdersRequest } from './types/types';
import { Request } from 'express';
@ApiTags('licenses')
@Controller('licenses')
export class LicensesController {
constructor(private readonly licensesService: LicensesService) {}
@ApiResponse({
status: HttpStatus.OK,
type: CreateOrdersResponse,
description: '成功時のレスポンス',
})
@ApiResponse({
status: HttpStatus.BAD_REQUEST,
description: '同一PONumberの注文がすでに存在する場合など',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.UNAUTHORIZED,
description: '認証エラー',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: '想定外のサーバーエラー',
type: ErrorResponse,
})
@ApiOperation({ operationId: 'createOrders' })
@ApiBearerAuth()
@Post('/orders')
async createOrders(
@Req() req: Request,
@Body() body: CreateOrdersRequest,
): Promise<CreateOrdersResponse> {
console.log(req.header('Authorization'));
console.log(body);
return {};
}
}

View File

@ -0,0 +1,9 @@
import { Module } from '@nestjs/common';
import { LicensesController } from './licenses.controller';
import { LicensesService } from './licenses.service';
@Module({
controllers: [LicensesController],
providers: [LicensesService],
})
export class LicensesModule {}

View File

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

View File

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

View File

@ -0,0 +1,11 @@
import { ApiProperty } from '@nestjs/swagger';
export class CreateOrdersRequest {
@ApiProperty()
poNumber: string;
@ApiProperty()
orderCount: number;
}
export class CreateOrdersResponse {}