Merged PR 304: API-IF実装

## 概要
[Task2338: API-IF実装](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/2338)

- 元PBI or タスクへのリンク(内容・目的などはそちらにあるはず)
- 何をどう変更したか、追加したライブラリなど
- このPull Requestでの対象/対象外
- 影響範囲(他の機能にも影響があるか)
新規のため、なし

## レビューポイント
- 特にレビューしてほしい箇所
- 軽微なものや自明なものは記載不要
- 修正範囲が大きい場合などに記載
- 全体的にや仕様を満たしているか等は本当に必要な時のみ記載

## UIの変更
- Before/Afterのスクショなど
- スクショ置き場

## 動作確認状況
- ローカル環境で確認
(POSTMANによる正常時の戻り値nullと各Error)

## 補足
- 相談、参考資料などがあれば
This commit is contained in:
maruyama.t 2023-08-04 02:08:42 +00:00
parent eb8c31cf05
commit 34ad2e489d
5 changed files with 158 additions and 33 deletions

View File

@ -423,7 +423,7 @@
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/GetOrderHistoriesResponce"
"$ref": "#/components/schemas/GetOrderHistoriesResponse"
}
}
}
@ -449,6 +449,59 @@
"security": [{ "bearer": [] }]
}
},
"/accounts/licenses/issue": {
"post": {
"operationId": "issueLicense",
"summary": "",
"parameters": [],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/IssueLicenseRequest" }
}
}
},
"responses": {
"200": {
"description": "成功時のレスポンス",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/IssueLicenseResponse"
}
}
}
},
"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": [] }]
}
},
"/users/confirm": {
"post": {
"operationId": "confirmUser",
@ -2044,7 +2097,7 @@
"status"
]
},
"GetOrderHistoriesResponce": {
"GetOrderHistoriesResponse": {
"type": "object",
"properties": {
"total": { "type": "number", "description": "合計件数" },
@ -2055,6 +2108,18 @@
},
"required": ["total", "orderHistories"]
},
"IssueLicenseRequest": {
"type": "object",
"properties": {
"orderedAccountId": {
"type": "number",
"description": "注文元アカウントID"
},
"poNumber": { "type": "string", "description": "POナンバー" }
},
"required": ["orderedAccountId", "poNumber"]
},
"IssueLicenseResponse": { "type": "object", "properties": {} },
"ConfirmRequest": {
"type": "object",
"properties": { "token": { "type": "string" } },

View File

@ -29,8 +29,9 @@ import {
GetPartnerLicensesRequest,
GetPartnerLicensesResponse,
GetOrderHistoriesRequest,
GetOrderHistoriesResponce,
LicenseOrder,
GetOrderHistoriesResponse,
IssueLicenseRequest,
IssueLicenseResponse,
} from './types/types';
import { USER_ROLES, ADMIN_ROLES, TIERS } from '../../constants';
import { AuthGuard } from '../../common/guards/auth/authguards';
@ -38,6 +39,7 @@ 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';
@ApiTags('accounts')
@Controller('accounts')
@ -332,7 +334,7 @@ export class AccountsController {
@Post('order-histories')
@ApiResponse({
status: HttpStatus.OK,
type: GetOrderHistoriesResponce,
type: GetOrderHistoriesResponse,
description: '成功時のレスポンス',
})
@ApiResponse({
@ -356,12 +358,60 @@ export class AccountsController {
async getOrderHistories(
@Req() req: Request,
@Body() body: GetOrderHistoriesRequest,
): Promise<GetOrderHistoriesResponce> {
): Promise<GetOrderHistoriesResponse> {
const { limit, offset, accountId } = body;
const getOrderHistoriesResponce =
const getOrderHistoriesResponse =
await this.accountService.getOrderHistories(limit, offset, accountId);
return getOrderHistoriesResponce;
return getOrderHistoriesResponse;
}
@Post('/licenses/issue')
@ApiResponse({
status: HttpStatus.OK,
type: IssueLicenseResponse,
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: 'issueLicense' })
@ApiBearerAuth()
@UseGuards(AuthGuard)
@UseGuards(
RoleGuard.requireds({
roles: [ADMIN_ROLES.ADMIN],
tiers: [TIERS.TIER1, TIERS.TIER2, TIERS.TIER3, TIERS.TIER4],
}),
)
async issueLicense(
@Req() req: Request,
@Body() body: IssueLicenseRequest,
): Promise<IssueLicenseResponse> {
console.log(req.header('Authorization'));
console.log(body);
const { orderedAccountId, poNumber } = body;
/*await this.licensesService.issueLicense(
orderedAccountId
poNumber,
);
*/
return {};
}
}

View File

@ -411,25 +411,25 @@ describe('createPartnerAccount', () => {
const offset = 0;
const limit = 20;
const responce = await service.getPartnerLicenses(limit, offset, accountId);
const response = await service.getPartnerLicenses(limit, offset, accountId);
expect(responce.total).toBe(2);
expect(response.total).toBe(2);
expect(responce.ownPartnerLicense.companyName).toBe('PARENTCORP');
expect(responce.ownPartnerLicense.tier).toBe(1);
expect(responce.ownPartnerLicense.stockLicense).toBe(3);
expect(responce.ownPartnerLicense.issuedRequested).toBe(15);
expect(responce.ownPartnerLicense.shortage).toBe(12);
expect(response.ownPartnerLicense.companyName).toBe('PARENTCORP');
expect(response.ownPartnerLicense.tier).toBe(1);
expect(response.ownPartnerLicense.stockLicense).toBe(3);
expect(response.ownPartnerLicense.issuedRequested).toBe(15);
expect(response.ownPartnerLicense.shortage).toBe(12);
expect(responce.childrenPartnerLicenses[0].companyName).toBe('CHILDCORP1');
expect(responce.childrenPartnerLicenses[0].tier).toBe(2);
expect(responce.childrenPartnerLicenses[0].stockLicense).toBe(1);
expect(responce.childrenPartnerLicenses[0].issueRequesting).toBe(10);
expect(response.childrenPartnerLicenses[0].companyName).toBe('CHILDCORP1');
expect(response.childrenPartnerLicenses[0].tier).toBe(2);
expect(response.childrenPartnerLicenses[0].stockLicense).toBe(1);
expect(response.childrenPartnerLicenses[0].issueRequesting).toBe(10);
expect(responce.childrenPartnerLicenses[1].companyName).toBe('CHILDCORP2');
expect(responce.childrenPartnerLicenses[1].tier).toBe(2);
expect(responce.childrenPartnerLicenses[1].stockLicense).toBe(2);
expect(responce.childrenPartnerLicenses[1].issueRequesting).toBe(5);
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);
});
});
@ -505,12 +505,12 @@ describe('getOrderHistories', () => {
const offset = 1;
const limit = 2;
const responce = await service.getOrderHistories(limit, offset, accountId);
const response = await service.getOrderHistories(limit, offset, accountId);
expect(responce.total).toBe(5);
expect(response.total).toBe(5);
expect(responce.orderHistories[0].poNumber).toBe('TEST004');
expect(responce.orderHistories[1].poNumber).toBe('TEST003');
expect(response.orderHistories[0].poNumber).toBe('TEST004');
expect(response.orderHistories[1].poNumber).toBe('TEST003');
});
it('注文履歴情報の取得に失敗した場合、エラーとなる', async () => {
const limit = 0;

View File

@ -20,7 +20,7 @@ import {
TypistGroup,
GetPartnerLicensesResponse,
PartnerLicenseInfo,
GetOrderHistoriesResponce,
GetOrderHistoriesResponse,
LicenseOrder,
} from './types/types';
import { DateWithZeroTime } from '../licenses/types/types';
@ -504,13 +504,13 @@ export class AccountsService {
* @param limit
* @param offset
* @param accountId
* @returns getOrderHistoriesResponce
* @returns getOrderHistoriesResponse
*/
async getOrderHistories(
limit: number,
offset: number,
accountId: number,
): Promise<GetOrderHistoriesResponce> {
): Promise<GetOrderHistoriesResponse> {
this.logger.log(`[IN] ${this.getOrderHistories.name}`);
try {
@ -542,7 +542,7 @@ export class AccountsService {
};
orderHistories.push(returnLicenseOrder);
}
const getOrderHistoriesResponse: GetOrderHistoriesResponce = {
const getOrderHistoriesResponse: GetOrderHistoriesResponse = {
total: licenseHistoryInfo.total,
orderHistories: orderHistories,
};

View File

@ -1,5 +1,5 @@
import { ApiProperty } from '@nestjs/swagger';
import { IsEmail, IsInt, IsOptional, Min } from 'class-validator';
import { IsEmail, IsInt, IsOptional, Matches, Min } from 'class-validator';
export class CreateAccountRequest {
@ApiProperty()
@ -218,9 +218,19 @@ export class LicenseOrder {
@ApiProperty({ description: '注文状態' })
status: string;
}
export class GetOrderHistoriesResponce {
export class GetOrderHistoriesResponse {
@ApiProperty({ description: '合計件数' })
total: number;
@ApiProperty({ type: [LicenseOrder] })
orderHistories: LicenseOrder[];
}
export class IssueLicenseRequest {
@ApiProperty({ description: '注文元アカウントID' })
orderedAccountId: number;
@ApiProperty({ description: 'POナンバー' })
@Matches(/^[A-Z0-9]+$/)
poNumber: string;
}
export class IssueLicenseResponse {}