## 概要 [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のスクショなど - スクショ置き場 ## 動作確認状況 - ローカルで確認 ## 補足 - 相談、参考資料などがあれば
314 lines
9.0 KiB
TypeScript
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;
|
|
}
|
|
}
|