maruyama.t eb3c7e55bd Merged PR 573: 音声ファイルアップロードAPI修正
## 概要
[Task3069: 音声ファイルアップロードAPI修正](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/3069)
[Task3070: 音声ファイルダウンロードAPI修正](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/3070)
[Task3071: テンプレートファイルダウンロードAPI修正](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/3071)
修正内容かぶるため、3本まとめてレビューお願いします。
- 元PBI or タスクへのリンク(内容・目的などはそちらにあるはず)
- 音声ファイルアップロードAPIを修正
 ・第五階層の場合のみチェックを追加
  ・アカウントがロックされている場合、エラー
  ・ユーザーにライセンスが未割当の場合、エラー
  ・ユーザーに紐づいたライセンスが有効期限切れの場合、エラー
- 音声ファイルダウンロード、テンプレートファイルダウンロードAPIを修正
 ・第五階層の場合のみチェックを追加
  ・ユーザーにライセンスが未割当の場合、エラー
  ・ユーザーに紐づいたライセンスが有効期限切れの場合、エラー
- 外部連携アプリ側の挙動の変化については考慮しない。
- ログ強化は別タスクで対応中。
- 影響範囲(他の機能にも影響があるか)
ファイル操作以外は影響なし。
旧式のユニットテストを修正。

## レビューポイント
- 音声ファイルアップロードのユニットテストを最新の状態にしたが、不足していないか。
~~- users.repositoryにユーザに紐づくライセンスが現在有効かどうかの判定を入れ込み、共通的に呼び出すようにしたが使いづらくないか(ライセンスが紐づいていない場合と有効期限切れの場合エラーとし、それ以外はtrueが帰る点について)~~

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

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

## 補足
- 相談、参考資料などがあれば
2023-11-14 13:16:46 +00:00

314 lines
9.0 KiB
TypeScript

import { HttpException, HttpStatus, Injectable, Logger } from '@nestjs/common';
import { makeErrorResponse } from '../../common/error/makeErrorResponse';
import { UsersRepositoryService } from '../../repositories/users/users.repository.service';
import { AccountsRepositoryService } from '../../repositories/accounts/accounts.repository.service';
import { AccountNotFoundError } from '../../repositories/accounts/errors/types';
import {
PoNumberAlreadyExistError,
LicenseNotExistError,
LicenseKeyAlreadyActivatedError,
CancelOrderFailedError,
} from '../../repositories/licenses/errors/types';
import { LicensesRepositoryService } from '../../repositories/licenses/licenses.repository.service';
import { UserNotFoundError } from '../../repositories/users/errors/types';
import {
DateWithZeroTime,
GetAllocatableLicensesResponse,
IssueCardLicensesResponse,
} from './types/types';
import { Context } from '../../common/log';
@Injectable()
export class LicensesService {
constructor(
private readonly usersRepository: UsersRepositoryService,
private readonly accountsRepository: AccountsRepositoryService,
private readonly licensesRepository: LicensesRepositoryService,
) {}
private readonly logger = new Logger(LicensesService.name);
/**
* license Orders
* @param token
* @param body
*/
async licenseOrders(
externalId: string,
poNumber: string,
orderCount: number,
): Promise<void> {
//アクセストークンからユーザーIDを取得する
this.logger.log(`[IN] ${this.licenseOrders.name}`);
let myAccountId: number;
let parentAccountId: number | undefined;
// ユーザIDからアカウントIDを取得する
try {
myAccountId = (
await this.usersRepository.findUserByExternalId(externalId)
).account_id;
} catch (e) {
this.logger.error(`error=${e}`);
switch (e.constructor) {
case UserNotFoundError:
throw new HttpException(
makeErrorResponse('E010204'),
HttpStatus.BAD_REQUEST,
);
default:
throw new HttpException(
makeErrorResponse('E009999'),
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
// 親アカウントIDを取得
try {
parentAccountId =
(await this.accountsRepository.findAccountById(myAccountId))
.parent_account_id ?? undefined;
// 親アカウントIDが取得できない場合はエラー
if (parentAccountId === undefined) {
throw new Error('parent account id is undefined');
}
} catch (e) {
this.logger.error(`error=${e}`);
switch (e.constructor) {
case AccountNotFoundError:
throw new HttpException(
makeErrorResponse('E010501'),
HttpStatus.BAD_REQUEST,
);
default:
throw new HttpException(
makeErrorResponse('E009999'),
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
try {
await this.licensesRepository.order(
poNumber,
myAccountId,
parentAccountId,
orderCount,
);
} catch (e) {
switch (e.constructor) {
case PoNumberAlreadyExistError:
throw new HttpException(
makeErrorResponse('E010401'),
HttpStatus.BAD_REQUEST,
);
default:
throw new HttpException(
makeErrorResponse('E009999'),
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
}
async issueCardLicenseKeys(
externalId: string,
createCount: number,
): Promise<IssueCardLicensesResponse> {
const issueCardLicensesResponse = new IssueCardLicensesResponse();
let myAccountId: number;
// ユーザIDからアカウントIDを取得する
try {
myAccountId = (
await this.usersRepository.findUserByExternalId(externalId)
).account_id;
} catch (e) {
this.logger.error(`error=${e}`);
switch (e.constructor) {
case UserNotFoundError:
throw new HttpException(
makeErrorResponse('E010204'),
HttpStatus.BAD_REQUEST,
);
default:
throw new HttpException(
makeErrorResponse('E009999'),
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
try {
const licenseKeys = await this.licensesRepository.createCardLicenses(
myAccountId,
createCount,
);
issueCardLicensesResponse.cardLicenseKeys = licenseKeys;
return issueCardLicensesResponse;
} catch (e) {
this.logger.error(`error=${e}`);
this.logger.error('get cardlicensekeys failed');
throw new HttpException(
makeErrorResponse('E009999'),
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
/**
* card license activate
* @param externalId
* @param cardLicenseKey
*/
async activateCardLicenseKey(
externalId: string,
cardLicenseKey: string,
): Promise<void> {
this.logger.log(
`[IN] ${this.activateCardLicenseKey.name}, argCardLicenseKey: ${cardLicenseKey}`,
);
let myAccountId: number;
// ユーザIDからアカウントIDを取得する
try {
myAccountId = (
await this.usersRepository.findUserByExternalId(externalId)
).account_id;
} catch (e) {
this.logger.error(`error=${e}`);
switch (e.constructor) {
case UserNotFoundError:
throw new HttpException(
makeErrorResponse('E010204'),
HttpStatus.BAD_REQUEST,
);
default:
throw new HttpException(
makeErrorResponse('E009999'),
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
// カードライセンスを取り込む
try {
await this.licensesRepository.activateCardLicense(
myAccountId,
cardLicenseKey,
);
} catch (e) {
this.logger.error(`error=${e}`);
this.logger.error('cardLicenseKey activate failed');
switch (e.constructor) {
case LicenseNotExistError:
throw new HttpException(
makeErrorResponse('E010801'),
HttpStatus.BAD_REQUEST,
);
case LicenseKeyAlreadyActivatedError:
throw new HttpException(
makeErrorResponse('E010802'),
HttpStatus.BAD_REQUEST,
);
default:
throw new HttpException(
makeErrorResponse('E009999'),
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
this.logger.log(`[OUT] ${this.activateCardLicenseKey.name}`);
return;
}
/**
* get allocatable lisences
* @param context
* @param userId
* @@returns AllocatableLicenseInfo[]
*/
async getAllocatableLicenses(
context: Context,
userId: string,
): Promise<GetAllocatableLicensesResponse> {
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}`,
);
}
}
/**
* ライセンス注文をキャンセルする
* @param context
* @param externalId
* @param poNumber
*/
async cancelOrder(
context: Context,
externalId: string,
poNumber: string,
): Promise<void> {
this.logger.log(
`[IN] [${context.trackingId}] ${this.cancelOrder.name} | params: { ` +
`externalId: ${externalId}, ` +
`poNumber: ${poNumber}, };`,
);
let myAccountId: number;
try {
// ユーザIDからアカウントIDを取得する
myAccountId = (
await this.usersRepository.findUserByExternalId(externalId)
).account_id;
// 注文キャンセル処理
await this.licensesRepository.cancelOrder(myAccountId, poNumber);
} catch (e) {
this.logger.error(`error=${e}`);
switch (e.constructor) {
case UserNotFoundError:
throw new HttpException(
makeErrorResponse('E010204'),
HttpStatus.BAD_REQUEST,
);
case CancelOrderFailedError:
throw new HttpException(
makeErrorResponse('E010808'),
HttpStatus.BAD_REQUEST,
);
default:
throw new HttpException(
makeErrorResponse('E009999'),
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
} finally {
this.logger.log(`[OUT] [${context.trackingId}] ${this.cancelOrder.name}`);
}
return;
}
}