makabe.t 2da40e278b Merged PR 371: API実装
## 概要
[Task2505: API実装](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/2505)

- ワークタイプ一覧取得APIとテストを実装しました。
  - ワークタイプテーブルのリポジトリも実装しています。

## レビューポイント
- リポジトリの実装に問題はないか
- テスト実装に不足はないか

## UIの変更
- なし

## 動作確認状況
- ローカルで確認
2023-09-01 00:24:01 +00:00

716 lines
20 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import {
Body,
Controller,
HttpStatus,
Post,
Get,
Req,
UseGuards,
Param,
} from '@nestjs/common';
import {
ApiOperation,
ApiResponse,
ApiTags,
ApiBearerAuth,
} from '@nestjs/swagger';
import { ErrorResponse } from '../../common/error/types/types';
import { Request } from 'express';
import { AccountsService } from './accounts.service';
import {
CreateAccountRequest,
CreateAccountResponse,
GetLicenseSummaryRequest,
GetLicenseSummaryResponse,
GetMyAccountResponse,
GetTypistGroupsResponse,
GetTypistsResponse,
CreatePartnerAccountRequest,
CreatePartnerAccountResponse,
GetPartnerLicensesRequest,
GetPartnerLicensesResponse,
GetOrderHistoriesRequest,
GetOrderHistoriesResponse,
IssueLicenseRequest,
IssueLicenseResponse,
GetDealersResponse,
CreateTypistGroupResponse,
CreateTypistGroupRequest,
GetTypistGroupResponse,
GetTypistGroupRequest,
UpdateTypistGroupRequest,
UpdateTypistGroupRequestParam,
CancelIssueRequest,
CancelIssueResponse,
GetWorktypesResponse,
CreateWorktypeResponse,
CreateWorktypesRequest,
} from './types/types';
import { USER_ROLES, ADMIN_ROLES, TIERS } from '../../constants';
import { AuthGuard } from '../../common/guards/auth/authguards';
import { RoleGuard } from '../../common/guards/role/roleguards';
import { retrieveAuthorizationToken } from '../../common/http/helper';
import { AccessToken } from '../../common/token';
import jwt from 'jsonwebtoken';
import { makeContext } from '../../common/log';
import { v4 as uuidv4 } from 'uuid';
@ApiTags('accounts')
@Controller('accounts')
export class AccountsController {
constructor(
private readonly accountService: AccountsService, //private readonly cryptoService: CryptoService,
) {}
@Post()
@ApiResponse({
status: HttpStatus.OK,
type: CreateAccountResponse,
description: '成功時のレスポンス',
})
@ApiResponse({
status: HttpStatus.BAD_REQUEST,
description: '登録済みユーザーからの登録など',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: '想定外のサーバーエラー',
type: ErrorResponse,
})
@ApiOperation({ operationId: 'createAccount' })
async createAccount(
@Body() body: CreateAccountRequest,
): Promise<CreateAccountResponse> {
const {
companyName,
country,
dealerAccountId,
adminMail,
adminPassword,
adminName,
acceptedTermsVersion,
} = body;
const role = USER_ROLES.NONE;
const context = makeContext(uuidv4());
await this.accountService.createAccount(
context,
companyName,
country,
dealerAccountId,
adminMail,
adminPassword,
adminName,
role,
acceptedTermsVersion,
);
return {};
}
@ApiResponse({
status: HttpStatus.OK,
type: GetLicenseSummaryResponse,
description: '成功時のレスポンス',
})
@ApiResponse({
status: HttpStatus.UNAUTHORIZED,
description: '認証エラー',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: '想定外のサーバーエラー',
type: ErrorResponse,
})
@ApiOperation({
operationId: 'getLicenseSummary',
description: '指定したアカウントのライセンス集計情報を取得します',
})
@ApiBearerAuth()
@UseGuards(AuthGuard)
@UseGuards(RoleGuard.requireds({ roles: [ADMIN_ROLES.ADMIN] }))
@Post('licenses/summary')
async getLicenseSummary(
@Req() req: Request,
@Body() body: GetLicenseSummaryRequest,
): Promise<GetLicenseSummaryResponse> {
const response = await this.accountService.getLicenseSummary(
body.accountId,
);
return response;
}
@ApiResponse({
status: HttpStatus.OK,
type: GetMyAccountResponse,
description: '成功時のレスポンス',
})
@ApiResponse({
status: HttpStatus.BAD_REQUEST,
description: '該当アカウントがDBに存在しない場合',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.UNAUTHORIZED,
description: '認証エラー',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: '想定外のサーバーエラー',
type: ErrorResponse,
})
@ApiOperation({
operationId: 'getMyAccount',
description: 'ログインしているユーザーのアカウント情報を取得します',
})
@ApiBearerAuth()
@UseGuards(AuthGuard)
@UseGuards(RoleGuard.requireds({ roles: [ADMIN_ROLES.ADMIN] }))
@Get('me')
async getMyAccount(@Req() req: Request): Promise<GetMyAccountResponse> {
// アクセストークン取得
const accessToken = retrieveAuthorizationToken(req);
const payload = jwt.decode(accessToken, { json: true }) as AccessToken;
//アカウントID取得処理
const accountInfo = await this.accountService.getMyAccountInfo(payload);
return accountInfo;
}
@ApiResponse({
status: HttpStatus.OK,
type: GetTypistsResponse,
description: '成功時のレスポンス',
})
@ApiResponse({
status: HttpStatus.UNAUTHORIZED,
description: '認証エラー',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: '想定外のサーバーエラー',
type: ErrorResponse,
})
@ApiOperation({
operationId: 'getTypists',
description:
'ログインしているユーザーのアカウント配下のタイピスト一覧を取得します',
})
@ApiBearerAuth()
@UseGuards(AuthGuard)
@Get('typists')
async getTypists(@Req() req: Request): Promise<GetTypistsResponse> {
const accessToken = retrieveAuthorizationToken(req);
const payload = jwt.decode(accessToken, { json: true }) as AccessToken;
const typists = await this.accountService.getTypists(payload.userId);
return { typists };
}
@ApiResponse({
status: HttpStatus.OK,
type: GetTypistGroupsResponse,
description: '成功時のレスポンス',
})
@ApiResponse({
status: HttpStatus.UNAUTHORIZED,
description: '認証エラー',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: '想定外のサーバーエラー',
type: ErrorResponse,
})
@ApiOperation({
operationId: 'getTypistGroups',
description:
'ログインしているユーザーのアカウント配下のタイピストグループ一覧を取得します',
})
@ApiBearerAuth()
@UseGuards(AuthGuard)
@Get('typist-groups')
async getTypistGroups(@Req() req: Request): Promise<GetTypistGroupsResponse> {
const accessToken = retrieveAuthorizationToken(req);
const payload = jwt.decode(accessToken, { json: true }) as AccessToken;
const typistGroups = await this.accountService.getTypistGroups(
payload.userId,
);
return { typistGroups };
}
@ApiResponse({
status: HttpStatus.OK,
type: GetTypistGroupResponse,
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: 'getTypistGroup',
description:
'ログインしているユーザーのアカウント配下でIDで指定されたタイピストグループを取得します',
})
@ApiBearerAuth()
@UseGuards(AuthGuard)
@UseGuards(RoleGuard.requireds({ roles: [ADMIN_ROLES.ADMIN] }))
@Get('typist-groups/:typistGroupId')
async getTypistGroup(
@Req() req: Request,
@Param() param: GetTypistGroupRequest,
): Promise<GetTypistGroupResponse> {
const { typistGroupId } = param;
// アクセストークン取得
const accessToken = retrieveAuthorizationToken(req);
const { userId } = jwt.decode(accessToken, { json: true }) as AccessToken;
const context = makeContext(userId);
const typistGroup = await this.accountService.getTypistGroup(
context,
userId,
typistGroupId,
);
return typistGroup;
}
@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<CreateTypistGroupResponse> {
const { typistGroupName, typistIds } = body;
// アクセストークン取得
const accessToken = retrieveAuthorizationToken(req);
const { userId } = jwt.decode(accessToken, { json: true }) as AccessToken;
const context = makeContext(userId);
await this.accountService.createTypistGroup(
context,
userId,
typistGroupName,
typistIds,
);
return {};
}
@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: 'updateTypistGroup',
description:
'ログインしているユーザーのアカウント配下でIDで指定されたタイピストグループを更新します',
})
@ApiBearerAuth()
@UseGuards(AuthGuard)
@UseGuards(RoleGuard.requireds({ roles: [ADMIN_ROLES.ADMIN] }))
@Post('typist-groups/:typistGroupId')
async updateTypistGroup(
@Req() req: Request,
@Body() body: UpdateTypistGroupRequest,
@Param() param: UpdateTypistGroupRequestParam,
): Promise<CreateTypistGroupResponse> {
const { typistGroupName, typistIds } = body;
const { typistGroupId } = param;
// アクセストークン取得
const accessToken = retrieveAuthorizationToken(req);
const { userId } = jwt.decode(accessToken, { json: true }) as AccessToken;
const context = makeContext(userId);
await this.accountService.updateTypistGroup(
context,
userId,
typistGroupId,
typistGroupName,
typistIds,
);
return {};
}
@Post('partner')
@ApiResponse({
status: HttpStatus.OK,
type: CreatePartnerAccountResponse,
description: '成功時のレスポンス',
})
@ApiResponse({
status: HttpStatus.UNAUTHORIZED,
description: '認証エラー',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.BAD_REQUEST,
description: '登録済みユーザーからの登録など',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: '想定外のサーバーエラー',
type: ErrorResponse,
})
@ApiOperation({ operationId: 'createPartnerAccount' })
@ApiBearerAuth()
@UseGuards(AuthGuard)
@UseGuards(
RoleGuard.requireds({
roles: [ADMIN_ROLES.ADMIN],
tiers: [TIERS.TIER1, TIERS.TIER2, TIERS.TIER3],
}),
)
async createPartnerAccount(
@Req() req: Request,
@Body() body: CreatePartnerAccountRequest,
): Promise<CreatePartnerAccountResponse> {
const { companyName, country, email, adminName } = body;
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,
adminName,
payload.userId,
payload.tier,
);
return {};
}
@Post('partner-licenses')
@ApiResponse({
status: HttpStatus.OK,
type: GetPartnerLicensesResponse,
description: '成功時のレスポンス',
})
@ApiResponse({
status: HttpStatus.UNAUTHORIZED,
description: '認証エラー',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: '想定外のサーバーエラー',
type: ErrorResponse,
})
@ApiOperation({ operationId: 'getPartnerLicenses' })
@ApiBearerAuth()
@UseGuards(AuthGuard)
@UseGuards(
RoleGuard.requireds({
roles: [ADMIN_ROLES.ADMIN],
tiers: [TIERS.TIER1, TIERS.TIER2, TIERS.TIER3, TIERS.TIER4],
}),
)
async getPartnerLicenses(
@Req() req: Request,
@Body() body: GetPartnerLicensesRequest,
): Promise<GetPartnerLicensesResponse> {
const { limit, offset, accountId } = body;
const getPartnerLicensesResponse =
await this.accountService.getPartnerLicenses(limit, offset, accountId);
return getPartnerLicensesResponse;
}
@Post('order-histories')
@ApiResponse({
status: HttpStatus.OK,
type: GetOrderHistoriesResponse,
description: '成功時のレスポンス',
})
@ApiResponse({
status: HttpStatus.UNAUTHORIZED,
description: '認証エラー',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: '想定外のサーバーエラー',
type: ErrorResponse,
})
@ApiOperation({ operationId: 'getOrderHistories' })
@ApiBearerAuth()
@UseGuards(AuthGuard)
@UseGuards(
RoleGuard.requireds({
roles: [ADMIN_ROLES.ADMIN],
}),
)
async getOrderHistories(
@Req() req: Request,
@Body() body: GetOrderHistoriesRequest,
): Promise<GetOrderHistoriesResponse> {
const { limit, offset, accountId } = body;
const getOrderHistoriesResponse =
await this.accountService.getOrderHistories(limit, offset, accountId);
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> {
const { orderedAccountId, poNumber } = body;
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 {};
}
@Get('/dealers')
@ApiResponse({
status: HttpStatus.OK,
type: GetDealersResponse,
description: '成功時のレスポンス',
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: '想定外のサーバーエラー',
type: ErrorResponse,
})
@ApiOperation({ operationId: 'getDealers' })
async getDealers(): Promise<GetDealersResponse> {
return await this.accountService.getDealers();
}
@Post('/issue/cancel')
@ApiResponse({
status: HttpStatus.OK,
type: CancelIssueResponse,
description: '成功時のレスポンス',
})
@ApiResponse({
status: HttpStatus.BAD_REQUEST,
description:
'対象注文のステータスが発行済以外/発行日から15日以降/ライセンスをユーザに割り当てている',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.UNAUTHORIZED,
description: '認証エラー',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: '想定外のサーバーエラー',
type: ErrorResponse,
})
@ApiOperation({
operationId: 'cancelIssue',
description: 'ライセンス発行をキャンセルします',
})
@ApiBearerAuth()
@UseGuards(AuthGuard)
@UseGuards(
RoleGuard.requireds({
roles: [ADMIN_ROLES.ADMIN],
tiers: [TIERS.TIER1, TIERS.TIER2],
}),
)
async cancelIssue(
@Req() req: Request,
@Body() body: CancelIssueRequest,
): Promise<CancelIssueResponse> {
const token = retrieveAuthorizationToken(req);
const payload = jwt.decode(token, { json: true }) as AccessToken;
const context = makeContext(payload.userId);
// TODO: 発行キャンセル処理。API実装のタスク2498で本実装
// await this.accountService.cancelIssue(
// context,
// body.poNumber,
// body.orderedAccountId,
// );
return {};
}
@Get('/worktypes')
@ApiResponse({
status: HttpStatus.OK,
type: GetWorktypesResponse,
description: '成功時のレスポンス',
})
@ApiResponse({
status: HttpStatus.UNAUTHORIZED,
description: '認証エラー',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: '想定外のサーバーエラー',
type: ErrorResponse,
})
@ApiOperation({ operationId: 'getWorktypes' })
@ApiBearerAuth()
@UseGuards(AuthGuard)
@UseGuards(RoleGuard.requireds({ roles: [ADMIN_ROLES.ADMIN] }))
async getWorktypes(@Req() req: Request): Promise<GetWorktypesResponse> {
const token = retrieveAuthorizationToken(req);
const { userId } = jwt.decode(token, { json: true }) as AccessToken;
const context = makeContext(userId);
const worktypes = await this.accountService.getWorktypes(context, userId);
return worktypes;
}
@Post('/worktypes')
@ApiResponse({
status: HttpStatus.OK,
type: CreateWorktypeResponse,
description: '成功時のレスポンス',
})
@ApiResponse({
status: HttpStatus.BAD_REQUEST,
description: 'WorktypeIDが重複 / WorktypeIDが空 / WorktypeIDが20件登録済み',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.UNAUTHORIZED,
description: '認証エラー',
type: ErrorResponse,
})
@ApiResponse({
status: HttpStatus.INTERNAL_SERVER_ERROR,
description: '想定外のサーバーエラー',
type: ErrorResponse,
})
@ApiOperation({ operationId: 'createWorktype' })
@ApiBearerAuth()
@UseGuards(AuthGuard)
@UseGuards(RoleGuard.requireds({ roles: [ADMIN_ROLES.ADMIN] }))
async createWorktype(
@Req() req: Request,
@Body() body: CreateWorktypesRequest,
): Promise<CreateWorktypeResponse> {
const { worktypeId, description } = body;
const token = retrieveAuthorizationToken(req);
const { userId } = jwt.decode(token, { json: true }) as AccessToken;
const context = makeContext(userId);
console.log(context.trackingId);
console.log(worktypeId);
console.log(description);
return {};
}
}