Merged PR 499: 修正②(files,licenses , Repositoiesのlicenses)
## 概要 [Task2836: 修正②(files,licenses , Repositoiesのlicenses)](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/2836) - feature - files - licenses - repositories - licenses - users - worktypes - entity - licenses - audio_files - audio_option_item - checkout_permission - アクセストークンをそのままService層に渡している箇所を修正し、必要なパラメータのみ渡すように修正 - クライアントの型生成 - 割り当て可能ライセンス取得APIのIFが変わったため ## レビューポイント - ## UIの変更 - Before/Afterのスクショなど - スクショ置き場 ## 動作確認状況 - ローカルでテストが通ることを確認 ## 補足 - 相談、参考資料などがあれば
This commit is contained in:
parent
c46d2bad61
commit
96848f5e54
@ -127,7 +127,7 @@ export interface AllocatableLicenseInfo {
|
||||
* @type {string}
|
||||
* @memberof AllocatableLicenseInfo
|
||||
*/
|
||||
'expiryDate': string;
|
||||
'expiryDate'?: string;
|
||||
}
|
||||
/**
|
||||
*
|
||||
|
||||
@ -4465,7 +4465,7 @@
|
||||
"licenseId": { "type": "number" },
|
||||
"expiryDate": { "format": "date-time", "type": "string" }
|
||||
},
|
||||
"required": ["licenseId", "expiryDate"]
|
||||
"required": ["licenseId"]
|
||||
},
|
||||
"GetAllocatableLicensesResponse": {
|
||||
"type": "object",
|
||||
|
||||
@ -444,6 +444,10 @@ export const makeDefaultUserGroupsRepositoryMockValue =
|
||||
name: 'GroupA',
|
||||
created_by: 'test',
|
||||
updated_by: 'test',
|
||||
created_at: new Date(),
|
||||
deleted_at: null,
|
||||
updated_at: null,
|
||||
userGroupMembers: null,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
@ -451,6 +455,10 @@ export const makeDefaultUserGroupsRepositoryMockValue =
|
||||
name: 'GroupB',
|
||||
created_by: 'test',
|
||||
updated_by: 'test',
|
||||
created_at: new Date(),
|
||||
deleted_at: null,
|
||||
updated_at: null,
|
||||
userGroupMembers: null,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
@ -2,6 +2,7 @@ import {
|
||||
Body,
|
||||
Controller,
|
||||
Get,
|
||||
HttpException,
|
||||
HttpStatus,
|
||||
Post,
|
||||
Query,
|
||||
@ -37,6 +38,7 @@ import { ADMIN_ROLES, USER_ROLES } from '../../constants';
|
||||
import { retrieveAuthorizationToken } from '../../common/http/helper';
|
||||
import { Request } from 'express';
|
||||
import { makeContext } from '../../common/log';
|
||||
import { makeErrorResponse } from '../../common/error/makeErrorResponse';
|
||||
|
||||
@ApiTags('files')
|
||||
@Controller('files')
|
||||
@ -75,10 +77,23 @@ export class FilesController {
|
||||
@Req() req: Request,
|
||||
@Body() body: AudioUploadFinishedRequest,
|
||||
): Promise<AudioUploadFinishedResponse> {
|
||||
const token = retrieveAuthorizationToken(req);
|
||||
const accessToken = jwt.decode(token, { json: true }) as AccessToken;
|
||||
const accessToken = retrieveAuthorizationToken(req);
|
||||
if (!accessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000107'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const decodedAccessToken = jwt.decode(accessToken, { json: true });
|
||||
if (!decodedAccessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000101'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const { userId } = decodedAccessToken as AccessToken;
|
||||
|
||||
const context = makeContext(accessToken.userId);
|
||||
const context = makeContext(userId);
|
||||
|
||||
const {
|
||||
url,
|
||||
@ -99,7 +114,7 @@ export class FilesController {
|
||||
|
||||
const res = await this.filesService.uploadFinished(
|
||||
context,
|
||||
accessToken.userId,
|
||||
userId,
|
||||
url,
|
||||
authorId,
|
||||
fileName,
|
||||
@ -149,10 +164,23 @@ export class FilesController {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
@Query() _query: AudioUploadLocationRequest,
|
||||
): Promise<AudioUploadLocationResponse> {
|
||||
const token = retrieveAuthorizationToken(req);
|
||||
const accessToken = jwt.decode(token, { json: true }) as AccessToken;
|
||||
const accessToken = retrieveAuthorizationToken(req);
|
||||
if (!accessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000107'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const decodedAccessToken = jwt.decode(accessToken, { json: true });
|
||||
if (!decodedAccessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000101'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const { userId } = decodedAccessToken as AccessToken;
|
||||
|
||||
const context = makeContext(accessToken.userId);
|
||||
const context = makeContext(userId);
|
||||
|
||||
const url = await this.filesService.publishUploadSas(context, accessToken);
|
||||
return { url };
|
||||
@ -195,14 +223,27 @@ export class FilesController {
|
||||
): Promise<AudioDownloadLocationResponse> {
|
||||
const { audioFileId } = body;
|
||||
|
||||
const token = retrieveAuthorizationToken(req);
|
||||
const accessToken = jwt.decode(token, { json: true }) as AccessToken;
|
||||
const accessToken = retrieveAuthorizationToken(req);
|
||||
if (!accessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000107'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const decodedAccessToken = jwt.decode(accessToken, { json: true });
|
||||
if (!decodedAccessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000101'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const { userId } = decodedAccessToken as AccessToken;
|
||||
|
||||
const context = makeContext(accessToken.userId);
|
||||
const context = makeContext(userId);
|
||||
|
||||
const url = await this.filesService.publishAudioFileDownloadSas(
|
||||
context,
|
||||
accessToken.userId,
|
||||
userId,
|
||||
audioFileId,
|
||||
);
|
||||
|
||||
@ -246,14 +287,27 @@ export class FilesController {
|
||||
): Promise<TemplateDownloadLocationResponse> {
|
||||
const { audioFileId } = body;
|
||||
|
||||
const token = retrieveAuthorizationToken(req);
|
||||
const accessToken = jwt.decode(token, { json: true }) as AccessToken;
|
||||
const accessToken = retrieveAuthorizationToken(req);
|
||||
if (!accessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000107'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const decodedAccessToken = jwt.decode(accessToken, { json: true });
|
||||
if (!decodedAccessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000101'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const { userId } = decodedAccessToken as AccessToken;
|
||||
|
||||
const context = makeContext(accessToken.userId);
|
||||
const context = makeContext(userId);
|
||||
|
||||
const url = await this.filesService.publishTemplateFileDownloadSas(
|
||||
context,
|
||||
accessToken.userId,
|
||||
userId,
|
||||
audioFileId,
|
||||
);
|
||||
|
||||
@ -287,8 +341,21 @@ export class FilesController {
|
||||
async uploadTemplateLocation(
|
||||
@Req() req: Request,
|
||||
): Promise<TemplateUploadLocationResponse> {
|
||||
const token = retrieveAuthorizationToken(req);
|
||||
const { userId } = jwt.decode(token, { json: true }) as AccessToken;
|
||||
const accessToken = retrieveAuthorizationToken(req);
|
||||
if (!accessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000107'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const decodedAccessToken = jwt.decode(accessToken, { json: true });
|
||||
if (!decodedAccessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000101'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const { userId } = decodedAccessToken as AccessToken;
|
||||
|
||||
const context = makeContext(userId);
|
||||
|
||||
@ -333,8 +400,21 @@ export class FilesController {
|
||||
@Body() body: TemplateUploadFinishedRequest,
|
||||
): Promise<TemplateUploadFinishedReqponse> {
|
||||
const { name, url } = body;
|
||||
const token = retrieveAuthorizationToken(req);
|
||||
const { userId } = jwt.decode(token, { json: true }) as AccessToken;
|
||||
const accessToken = retrieveAuthorizationToken(req);
|
||||
if (!accessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000107'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const decodedAccessToken = jwt.decode(accessToken, { json: true });
|
||||
if (!decodedAccessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000101'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const { userId } = decodedAccessToken as AccessToken;
|
||||
|
||||
const context = makeContext(userId);
|
||||
await this.filesService.templateUploadFinished(context, userId, url, name);
|
||||
|
||||
@ -35,11 +35,10 @@ describe('音声ファイルアップロードURL取得', () => {
|
||||
);
|
||||
|
||||
expect(
|
||||
await service.publishUploadSas(makeContext('trackingId'), {
|
||||
userId: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx',
|
||||
role: 'Author',
|
||||
tier: 5,
|
||||
}),
|
||||
await service.publishUploadSas(
|
||||
makeContext('trackingId'),
|
||||
'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx',
|
||||
),
|
||||
).toEqual('https://blob-storage?sas-token');
|
||||
});
|
||||
|
||||
@ -57,11 +56,10 @@ describe('音声ファイルアップロードURL取得', () => {
|
||||
);
|
||||
|
||||
expect(
|
||||
await service.publishUploadSas(makeContext('trackingId'), {
|
||||
userId: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx',
|
||||
role: 'Author',
|
||||
tier: 5,
|
||||
}),
|
||||
await service.publishUploadSas(
|
||||
makeContext('trackingId'),
|
||||
'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx',
|
||||
),
|
||||
).toEqual('https://blob-storage?sas-token');
|
||||
});
|
||||
|
||||
@ -78,11 +76,10 @@ describe('音声ファイルアップロードURL取得', () => {
|
||||
);
|
||||
|
||||
await expect(
|
||||
service.publishUploadSas(makeContext('trackingId'), {
|
||||
userId: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx',
|
||||
role: 'Author',
|
||||
tier: 5,
|
||||
}),
|
||||
service.publishUploadSas(
|
||||
makeContext('trackingId'),
|
||||
'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx',
|
||||
),
|
||||
).rejects.toEqual(
|
||||
new HttpException(makeErrorResponse('E009999'), HttpStatus.UNAUTHORIZED),
|
||||
);
|
||||
@ -102,11 +99,10 @@ describe('音声ファイルアップロードURL取得', () => {
|
||||
blobParam.publishUploadSas = new Error('Azure service down');
|
||||
|
||||
await expect(
|
||||
service.publishUploadSas(makeContext('trackingId'), {
|
||||
userId: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx',
|
||||
role: 'Author',
|
||||
tier: 5,
|
||||
}),
|
||||
service.publishUploadSas(
|
||||
makeContext('trackingId'),
|
||||
'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx',
|
||||
),
|
||||
).rejects.toEqual(
|
||||
new HttpException(makeErrorResponse('E009999'), HttpStatus.UNAUTHORIZED),
|
||||
);
|
||||
@ -295,7 +291,7 @@ describe('タスク作成', () => {
|
||||
});
|
||||
|
||||
describe('音声ファイルダウンロードURL取得', () => {
|
||||
let source: DataSource = null;
|
||||
let source: DataSource | null = null;
|
||||
beforeEach(async () => {
|
||||
source = new DataSource({
|
||||
type: 'sqlite',
|
||||
@ -308,11 +304,13 @@ describe('音声ファイルダウンロードURL取得', () => {
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
if (!source) return;
|
||||
await source.destroy();
|
||||
source = null;
|
||||
});
|
||||
|
||||
it('ダウンロードSASトークンが乗っているURLを取得できる', async () => {
|
||||
if (!source) fail();
|
||||
const { id: accountId } = await makeTestSimpleAccount(source);
|
||||
const {
|
||||
external_id: externalId,
|
||||
@ -333,7 +331,7 @@ describe('音声ファイルダウンロードURL取得', () => {
|
||||
'test.zip',
|
||||
'InProgress',
|
||||
undefined,
|
||||
authorId,
|
||||
authorId ?? '',
|
||||
);
|
||||
|
||||
const blobParam = makeBlobstorageServiceMockValue();
|
||||
@ -341,6 +339,7 @@ describe('音声ファイルダウンロードURL取得', () => {
|
||||
blobParam.fileExists = true;
|
||||
|
||||
const module = await makeTestingModuleWithBlob(source, blobParam);
|
||||
if (!module) fail();
|
||||
const service = module.get<FilesService>(FilesService);
|
||||
|
||||
expect(
|
||||
@ -353,6 +352,7 @@ describe('音声ファイルダウンロードURL取得', () => {
|
||||
});
|
||||
|
||||
it('Typistの場合、タスクのステータスが[Inprogress,Pending]以外でエラー', async () => {
|
||||
if (!source) fail();
|
||||
const { id: accountId } = await makeTestSimpleAccount(source);
|
||||
const { external_id: externalId, id: userId } = await makeTestUser(source, {
|
||||
account_id: accountId,
|
||||
@ -382,6 +382,7 @@ describe('音声ファイルダウンロードURL取得', () => {
|
||||
blobParam.fileExists = true;
|
||||
|
||||
const module = await makeTestingModuleWithBlob(source, blobParam);
|
||||
if (!module) fail();
|
||||
const service = module.get<FilesService>(FilesService);
|
||||
|
||||
await expect(
|
||||
@ -396,6 +397,7 @@ describe('音声ファイルダウンロードURL取得', () => {
|
||||
});
|
||||
|
||||
it('Typistの場合、自身が担当するタスクでない場合エラー', async () => {
|
||||
if (!source) fail();
|
||||
const { id: accountId } = await makeTestSimpleAccount(source);
|
||||
const { external_id: externalId } = await makeTestUser(source, {
|
||||
account_id: accountId,
|
||||
@ -429,6 +431,7 @@ describe('音声ファイルダウンロードURL取得', () => {
|
||||
blobParam.fileExists = true;
|
||||
|
||||
const module = await makeTestingModuleWithBlob(source, blobParam);
|
||||
if (!module) fail();
|
||||
const service = module.get<FilesService>(FilesService);
|
||||
|
||||
await expect(
|
||||
@ -443,6 +446,7 @@ describe('音声ファイルダウンロードURL取得', () => {
|
||||
});
|
||||
|
||||
it('Authorの場合、自身が登録したタスクでない場合エラー', async () => {
|
||||
if (!source) fail();
|
||||
const { id: accountId } = await makeTestSimpleAccount(source);
|
||||
const { external_id: externalId, id: userId } = await makeTestUser(source, {
|
||||
account_id: accountId,
|
||||
@ -467,6 +471,7 @@ describe('音声ファイルダウンロードURL取得', () => {
|
||||
blobParam.fileExists = true;
|
||||
|
||||
const module = await makeTestingModuleWithBlob(source, blobParam);
|
||||
if (!module) fail();
|
||||
const service = module.get<FilesService>(FilesService);
|
||||
|
||||
await expect(
|
||||
@ -481,6 +486,7 @@ describe('音声ファイルダウンロードURL取得', () => {
|
||||
});
|
||||
|
||||
it('Taskが存在しない場合はエラーとなる', async () => {
|
||||
if (!source) fail();
|
||||
const { id: accountId } = await makeTestSimpleAccount(source);
|
||||
const { external_id: externalId } = await makeTestUser(source, {
|
||||
account_id: accountId,
|
||||
@ -492,6 +498,7 @@ describe('音声ファイルダウンロードURL取得', () => {
|
||||
const blobParam = makeBlobstorageServiceMockValue();
|
||||
|
||||
const module = await makeTestingModuleWithBlob(source, blobParam);
|
||||
if (!module) fail();
|
||||
const service = module.get<FilesService>(FilesService);
|
||||
|
||||
await expect(
|
||||
@ -506,6 +513,7 @@ describe('音声ファイルダウンロードURL取得', () => {
|
||||
});
|
||||
|
||||
it('blobストレージにファイルが存在しない場合はエラーとなる', async () => {
|
||||
if (!source) fail();
|
||||
const { id: accountId } = await makeTestSimpleAccount(source);
|
||||
const {
|
||||
external_id: externalId,
|
||||
@ -526,7 +534,7 @@ describe('音声ファイルダウンロードURL取得', () => {
|
||||
'test.zip',
|
||||
'InProgress',
|
||||
undefined,
|
||||
authorId,
|
||||
authorId ?? '',
|
||||
);
|
||||
|
||||
const blobParam = makeBlobstorageServiceMockValue();
|
||||
@ -534,6 +542,7 @@ describe('音声ファイルダウンロードURL取得', () => {
|
||||
blobParam.fileExists = false;
|
||||
|
||||
const module = await makeTestingModuleWithBlob(source, blobParam);
|
||||
if (!module) fail();
|
||||
const service = module.get<FilesService>(FilesService);
|
||||
|
||||
await expect(
|
||||
@ -549,7 +558,7 @@ describe('音声ファイルダウンロードURL取得', () => {
|
||||
});
|
||||
|
||||
describe('テンプレートファイルダウンロードURL取得', () => {
|
||||
let source: DataSource = null;
|
||||
let source: DataSource | null = null;
|
||||
beforeEach(async () => {
|
||||
source = new DataSource({
|
||||
type: 'sqlite',
|
||||
@ -562,11 +571,13 @@ describe('テンプレートファイルダウンロードURL取得', () => {
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
if (!source) return;
|
||||
await source.destroy();
|
||||
source = null;
|
||||
});
|
||||
|
||||
it('ダウンロードSASトークンが乗っているURLを取得できる', async () => {
|
||||
if (!source) fail();
|
||||
const { id: accountId } = await makeTestSimpleAccount(source);
|
||||
const { external_id: externalId, author_id: authorId } = await makeTestUser(
|
||||
source,
|
||||
@ -586,7 +597,7 @@ describe('テンプレートファイルダウンロードURL取得', () => {
|
||||
'test.zip',
|
||||
'InProgress',
|
||||
undefined,
|
||||
authorId,
|
||||
authorId ?? '',
|
||||
);
|
||||
|
||||
const blobParam = makeBlobstorageServiceMockValue();
|
||||
@ -594,6 +605,7 @@ describe('テンプレートファイルダウンロードURL取得', () => {
|
||||
blobParam.fileExists = true;
|
||||
|
||||
const module = await makeTestingModuleWithBlob(source, blobParam);
|
||||
if (!module) fail();
|
||||
const service = module.get<FilesService>(FilesService);
|
||||
|
||||
expect(
|
||||
@ -606,6 +618,7 @@ describe('テンプレートファイルダウンロードURL取得', () => {
|
||||
});
|
||||
|
||||
it('Typistの場合、タスクのステータスが[Inprogress,Pending]以外でエラー', async () => {
|
||||
if (!source) fail();
|
||||
const { id: accountId } = await makeTestSimpleAccount(source);
|
||||
const { external_id: externalId, id: userId } = await makeTestUser(source, {
|
||||
account_id: accountId,
|
||||
@ -629,6 +642,7 @@ describe('テンプレートファイルダウンロードURL取得', () => {
|
||||
blobParam.fileExists = true;
|
||||
|
||||
const module = await makeTestingModuleWithBlob(source, blobParam);
|
||||
if (!module) fail();
|
||||
const service = module.get<FilesService>(FilesService);
|
||||
|
||||
await expect(
|
||||
@ -643,6 +657,7 @@ describe('テンプレートファイルダウンロードURL取得', () => {
|
||||
});
|
||||
|
||||
it('Typistの場合、自身が担当するタスクでない場合エラー', async () => {
|
||||
if (!source) fail();
|
||||
const { id: accountId } = await makeTestSimpleAccount(source);
|
||||
const { external_id: externalId } = await makeTestUser(source, {
|
||||
account_id: accountId,
|
||||
@ -672,6 +687,7 @@ describe('テンプレートファイルダウンロードURL取得', () => {
|
||||
blobParam.fileExists = true;
|
||||
|
||||
const module = await makeTestingModuleWithBlob(source, blobParam);
|
||||
if (!module) fail();
|
||||
const service = module.get<FilesService>(FilesService);
|
||||
|
||||
await expect(
|
||||
@ -686,6 +702,7 @@ describe('テンプレートファイルダウンロードURL取得', () => {
|
||||
});
|
||||
|
||||
it('Authorの場合、自身が登録したタスクでない場合エラー', async () => {
|
||||
if (!source) fail();
|
||||
const { id: accountId } = await makeTestSimpleAccount(source);
|
||||
const { external_id: externalId } = await makeTestUser(source, {
|
||||
account_id: accountId,
|
||||
@ -710,6 +727,7 @@ describe('テンプレートファイルダウンロードURL取得', () => {
|
||||
blobParam.fileExists = true;
|
||||
|
||||
const module = await makeTestingModuleWithBlob(source, blobParam);
|
||||
if (!module) fail();
|
||||
const service = module.get<FilesService>(FilesService);
|
||||
|
||||
await expect(
|
||||
@ -724,6 +742,7 @@ describe('テンプレートファイルダウンロードURL取得', () => {
|
||||
});
|
||||
|
||||
it('Taskが存在しない場合はエラーとなる', async () => {
|
||||
if (!source) fail();
|
||||
const { id: accountId } = await makeTestSimpleAccount(source);
|
||||
const { external_id: externalId } = await makeTestUser(source, {
|
||||
account_id: accountId,
|
||||
@ -735,6 +754,7 @@ describe('テンプレートファイルダウンロードURL取得', () => {
|
||||
const blobParam = makeBlobstorageServiceMockValue();
|
||||
|
||||
const module = await makeTestingModuleWithBlob(source, blobParam);
|
||||
if (!module) fail();
|
||||
const service = module.get<FilesService>(FilesService);
|
||||
|
||||
await expect(
|
||||
@ -749,6 +769,7 @@ describe('テンプレートファイルダウンロードURL取得', () => {
|
||||
});
|
||||
|
||||
it('blobストレージにファイルが存在しない場合はエラーとなる', async () => {
|
||||
if (!source) fail();
|
||||
const { id: accountId } = await makeTestSimpleAccount(source);
|
||||
const { external_id: externalId, author_id: authorId } = await makeTestUser(
|
||||
source,
|
||||
@ -768,7 +789,7 @@ describe('テンプレートファイルダウンロードURL取得', () => {
|
||||
'test.zip',
|
||||
'InProgress',
|
||||
undefined,
|
||||
authorId,
|
||||
authorId ?? '',
|
||||
);
|
||||
|
||||
const blobParam = makeBlobstorageServiceMockValue();
|
||||
@ -776,6 +797,7 @@ describe('テンプレートファイルダウンロードURL取得', () => {
|
||||
blobParam.fileExists = false;
|
||||
|
||||
const module = await makeTestingModuleWithBlob(source, blobParam);
|
||||
if (!module) fail();
|
||||
const service = module.get<FilesService>(FilesService);
|
||||
|
||||
await expect(
|
||||
@ -791,7 +813,7 @@ describe('テンプレートファイルダウンロードURL取得', () => {
|
||||
});
|
||||
|
||||
describe('publishTemplateFileUploadSas', () => {
|
||||
let source: DataSource = null;
|
||||
let source: DataSource | null = null;
|
||||
beforeEach(async () => {
|
||||
source = new DataSource({
|
||||
type: 'sqlite',
|
||||
@ -804,12 +826,15 @@ describe('publishTemplateFileUploadSas', () => {
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
if (!source) return;
|
||||
await source.destroy();
|
||||
source = null;
|
||||
});
|
||||
|
||||
it('テンプレートファイルアップロードSASトークンが乗っているURLを取得できる', async () => {
|
||||
if (!source) fail();
|
||||
const module = await makeTestingModule(source);
|
||||
if (!module) fail();
|
||||
const service = module.get<FilesService>(FilesService);
|
||||
// 第五階層のアカウント作成
|
||||
const { account, admin } = await makeTestAccount(source, { tier: 5 });
|
||||
@ -832,7 +857,9 @@ describe('publishTemplateFileUploadSas', () => {
|
||||
});
|
||||
|
||||
it('blobストレージにコンテナが存在しない場合はエラーとなる', async () => {
|
||||
if (!source) fail();
|
||||
const module = await makeTestingModule(source);
|
||||
if (!module) fail();
|
||||
const service = module.get<FilesService>(FilesService);
|
||||
// 第五階層のアカウント作成
|
||||
const { admin } = await makeTestAccount(source, { tier: 5 });
|
||||
@ -858,7 +885,9 @@ describe('publishTemplateFileUploadSas', () => {
|
||||
});
|
||||
|
||||
it('SASトークンの取得に失敗した場合はエラーとなる', async () => {
|
||||
if (!source) fail();
|
||||
const module = await makeTestingModule(source);
|
||||
if (!module) fail();
|
||||
const service = module.get<FilesService>(FilesService);
|
||||
// 第五階層のアカウント作成
|
||||
const { admin } = await makeTestAccount(source, { tier: 5 });
|
||||
@ -887,7 +916,7 @@ describe('publishTemplateFileUploadSas', () => {
|
||||
});
|
||||
|
||||
describe('templateUploadFinished', () => {
|
||||
let source: DataSource = null;
|
||||
let source: DataSource | null = null;
|
||||
beforeEach(async () => {
|
||||
source = new DataSource({
|
||||
type: 'sqlite',
|
||||
@ -900,12 +929,15 @@ describe('templateUploadFinished', () => {
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
if (!source) return;
|
||||
await source.destroy();
|
||||
source = null;
|
||||
});
|
||||
|
||||
it('アップロード完了後のテンプレートファイル情報をDBに保存できる(新規追加)', async () => {
|
||||
if (!source) fail();
|
||||
const module = await makeTestingModule(source);
|
||||
if (!module) fail();
|
||||
const service = module.get<FilesService>(FilesService);
|
||||
// 第五階層のアカウント作成
|
||||
const { account, admin } = await makeTestAccount(source, { tier: 5 });
|
||||
@ -937,7 +969,9 @@ describe('templateUploadFinished', () => {
|
||||
});
|
||||
|
||||
it('アップロード完了後のテンプレートファイル情報をDBに保存できる(更新)', async () => {
|
||||
if (!source) fail();
|
||||
const module = await makeTestingModule(source);
|
||||
if (!module) fail();
|
||||
const service = module.get<FilesService>(FilesService);
|
||||
// 第五階層のアカウント作成
|
||||
const { account, admin } = await makeTestAccount(source, { tier: 5 });
|
||||
@ -975,7 +1009,9 @@ describe('templateUploadFinished', () => {
|
||||
});
|
||||
|
||||
it('DBへの保存に失敗した場合はエラーとなる', async () => {
|
||||
if (!source) fail();
|
||||
const module = await makeTestingModule(source);
|
||||
if (!module) fail();
|
||||
const service = module.get<FilesService>(FilesService);
|
||||
// 第五階層のアカウント作成
|
||||
const { account, admin } = await makeTestAccount(source, { tier: 5 });
|
||||
|
||||
@ -24,6 +24,7 @@ import {
|
||||
} from '../../repositories/tasks/errors/types';
|
||||
import { Context } from '../../common/log';
|
||||
import { TemplateFilesRepositoryService } from '../../repositories/template_files/template_files.repository.service';
|
||||
import { AccountNotFoundError } from '../../repositories/accounts/errors/types';
|
||||
|
||||
@Injectable()
|
||||
export class FilesService {
|
||||
@ -206,7 +207,7 @@ export class FilesService {
|
||||
*/
|
||||
async publishUploadSas(
|
||||
context: Context,
|
||||
token: AccessToken,
|
||||
externalId: string,
|
||||
): Promise<string> {
|
||||
this.logger.log(
|
||||
`[IN] [${context.trackingId}] ${this.publishUploadSas.name}`,
|
||||
@ -216,10 +217,11 @@ export class FilesService {
|
||||
let accountId: number;
|
||||
let country: string;
|
||||
try {
|
||||
const user = await this.usersRepository.findUserByExternalId(
|
||||
token.userId,
|
||||
);
|
||||
accountId = user.account.id;
|
||||
const user = await this.usersRepository.findUserByExternalId(externalId);
|
||||
if (!user.account) {
|
||||
throw new AccountNotFoundError('account not found.');
|
||||
}
|
||||
accountId = user.account_id;
|
||||
country = user.account.country;
|
||||
} catch (e) {
|
||||
this.logger.error(`error=${e}`);
|
||||
@ -291,14 +293,17 @@ export class FilesService {
|
||||
let userId: number;
|
||||
let country: string;
|
||||
let isTypist: boolean;
|
||||
let authorId: string;
|
||||
let authorId: string | undefined;
|
||||
try {
|
||||
const user = await this.usersRepository.findUserByExternalId(externalId);
|
||||
if (!user.account) {
|
||||
throw new AccountNotFoundError('account not found.');
|
||||
}
|
||||
accountId = user.account.id;
|
||||
userId = user.id;
|
||||
country = user.account.country;
|
||||
isTypist = user.role === USER_ROLES.TYPIST;
|
||||
authorId = user.author_id;
|
||||
authorId = user.author_id ?? undefined;
|
||||
} catch (e) {
|
||||
this.logger.error(`error=${e}`);
|
||||
|
||||
@ -321,7 +326,7 @@ export class FilesService {
|
||||
accountId,
|
||||
status,
|
||||
);
|
||||
const file = task.file;
|
||||
const { file } = task;
|
||||
|
||||
// タスクに紐づく音声ファイルだけが消される場合がある。
|
||||
// その場合はダウンロード不可なので不在エラーとして扱う
|
||||
@ -332,9 +337,9 @@ export class FilesService {
|
||||
}
|
||||
|
||||
// ユーザーがAuthorの場合、自身が追加したタスクでない場合はエラー
|
||||
if (!isTypist && task.file.author_id !== authorId) {
|
||||
if (!isTypist && file.author_id !== authorId) {
|
||||
throw new AuthorUserNotMatchError(
|
||||
`task author is not match. audio_file_id:${audioFileId}, task.file.author_id:${task.file.author_id}, authorId:${authorId}`,
|
||||
`task author is not match. audio_file_id:${audioFileId}, task.file.author_id:${file.author_id}, authorId:${authorId}`,
|
||||
);
|
||||
}
|
||||
|
||||
@ -425,14 +430,17 @@ export class FilesService {
|
||||
let userId: number;
|
||||
let country: string;
|
||||
let isTypist: boolean;
|
||||
let authorId: string;
|
||||
let authorId: string | undefined;
|
||||
try {
|
||||
const user = await this.usersRepository.findUserByExternalId(externalId);
|
||||
accountId = user.account.id;
|
||||
if (!user.account) {
|
||||
throw new AccountNotFoundError('account not found.');
|
||||
}
|
||||
accountId = user.account_id;
|
||||
userId = user.id;
|
||||
country = user.account.country;
|
||||
isTypist = user.role === USER_ROLES.TYPIST;
|
||||
authorId = user.author_id;
|
||||
authorId = user.author_id ?? undefined;
|
||||
} catch (e) {
|
||||
this.logger.error(`error=${e}`);
|
||||
this.logger.log(
|
||||
@ -454,6 +462,15 @@ export class FilesService {
|
||||
accountId,
|
||||
status,
|
||||
);
|
||||
const { file } = task;
|
||||
|
||||
// タスクに紐づく音声ファイルだけが消される場合がある。
|
||||
// その場合はダウンロード不可なので不在エラーとして扱う
|
||||
if (!file) {
|
||||
throw new AudioFileNotFoundError(
|
||||
`Audio file is not exists in DB. audio_file_id:${audioFileId}`,
|
||||
);
|
||||
}
|
||||
|
||||
const template_file = task.template_file;
|
||||
|
||||
@ -466,9 +483,9 @@ export class FilesService {
|
||||
}
|
||||
|
||||
// ユーザーがAuthorの場合、自身が追加したタスクでない場合はエラー
|
||||
if (!isTypist && task.file.author_id !== authorId) {
|
||||
if (!isTypist && file.author_id !== authorId) {
|
||||
throw new AuthorUserNotMatchError(
|
||||
`task author is not match. audio_file_id:${audioFileId}, task.file.author_id:${task.file.author_id}, authorId:${authorId}`,
|
||||
`task author is not match. audio_file_id:${audioFileId}, task.file.author_id:${file.author_id}, authorId:${authorId}`,
|
||||
);
|
||||
}
|
||||
|
||||
@ -515,6 +532,7 @@ export class FilesService {
|
||||
makeErrorResponse('E010603'),
|
||||
HttpStatus.BAD_REQUEST,
|
||||
);
|
||||
case AudioFileNotFoundError:
|
||||
case TemplateFileNotFoundError:
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E010701'),
|
||||
@ -552,15 +570,18 @@ export class FilesService {
|
||||
`[IN] [${context.trackingId}] ${this.publishTemplateFileUploadSas.name} | params: { externalId: ${externalId} };`,
|
||||
);
|
||||
try {
|
||||
const {
|
||||
account: { id: accountId, country },
|
||||
} = await this.usersRepository.findUserByExternalId(externalId);
|
||||
const { account } = await this.usersRepository.findUserByExternalId(
|
||||
externalId,
|
||||
);
|
||||
if (!account) {
|
||||
throw new AccountNotFoundError('account not found.');
|
||||
}
|
||||
|
||||
// 国に応じたリージョンのBlobストレージにコンテナが存在するか確認
|
||||
const isContainerExists = await this.blobStorageService.containerExists(
|
||||
context,
|
||||
accountId,
|
||||
country,
|
||||
account.id,
|
||||
account.country,
|
||||
);
|
||||
if (!isContainerExists) {
|
||||
throw new Error('container not found.');
|
||||
@ -569,8 +590,8 @@ export class FilesService {
|
||||
// SASトークン発行
|
||||
const url = await this.blobStorageService.publishTemplateUploadSas(
|
||||
context,
|
||||
accountId,
|
||||
country,
|
||||
account.id,
|
||||
account.country,
|
||||
);
|
||||
|
||||
return url;
|
||||
|
||||
@ -134,7 +134,7 @@ export const makeDefaultUsersRepositoryMockValue =
|
||||
created_by: 'test',
|
||||
created_at: new Date(),
|
||||
updated_by: null,
|
||||
updated_at: null,
|
||||
updated_at: new Date(),
|
||||
auto_renew: true,
|
||||
license_alert: true,
|
||||
notification: true,
|
||||
@ -157,7 +157,7 @@ export const makeDefaultUsersRepositoryMockValue =
|
||||
created_by: '',
|
||||
created_at: new Date(),
|
||||
updated_by: '',
|
||||
updated_at: null,
|
||||
updated_at: new Date(),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@ -98,7 +98,7 @@ export const createTask = async (
|
||||
export const makeTestingModuleWithBlob = async (
|
||||
datasource: DataSource,
|
||||
blobStorageService: BlobstorageServiceMockValue,
|
||||
): Promise<TestingModule> => {
|
||||
): Promise<TestingModule | undefined> => {
|
||||
try {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
imports: [
|
||||
|
||||
@ -2,6 +2,7 @@ import {
|
||||
Body,
|
||||
Controller,
|
||||
Get,
|
||||
HttpException,
|
||||
HttpStatus,
|
||||
Post,
|
||||
Req,
|
||||
@ -34,6 +35,7 @@ import { RoleGuard } from '../../common/guards/role/roleguards';
|
||||
import { ADMIN_ROLES, TIERS } from '../../constants';
|
||||
import jwt from 'jsonwebtoken';
|
||||
import { makeContext } from '../../common/log';
|
||||
import { makeErrorResponse } from '../../common/error/makeErrorResponse';
|
||||
|
||||
@ApiTags('licenses')
|
||||
@Controller('licenses')
|
||||
@ -73,12 +75,26 @@ export class LicensesController {
|
||||
@Req() req: Request,
|
||||
@Body() body: CreateOrdersRequest,
|
||||
): Promise<CreateOrdersResponse> {
|
||||
const accessToken = retrieveAuthorizationToken(req);
|
||||
const payload = jwt.decode(accessToken, { json: true }) as AccessToken;
|
||||
// TODO strictNullChecks対応
|
||||
const accessToken = retrieveAuthorizationToken(req) as string;
|
||||
if (!accessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000107'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const decodedAccessToken = jwt.decode(accessToken, { json: true });
|
||||
if (!decodedAccessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000101'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const { userId } = decodedAccessToken as AccessToken;
|
||||
|
||||
// ライセンス注文処理
|
||||
await this.licensesService.licenseOrders(
|
||||
payload,
|
||||
userId,
|
||||
body.poNumber,
|
||||
body.orderCount,
|
||||
);
|
||||
@ -111,11 +127,25 @@ export class LicensesController {
|
||||
@Req() req: Request,
|
||||
@Body() body: IssueCardLicensesRequest,
|
||||
): Promise<IssueCardLicensesResponse> {
|
||||
const accessToken = retrieveAuthorizationToken(req);
|
||||
const payload = jwt.decode(accessToken, { json: true }) as AccessToken;
|
||||
// TODO strictNullChecks対応
|
||||
const accessToken = retrieveAuthorizationToken(req) as string;
|
||||
if (!accessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000107'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const decodedAccessToken = jwt.decode(accessToken, { json: true });
|
||||
if (!decodedAccessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000101'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const { userId } = decodedAccessToken as AccessToken;
|
||||
|
||||
const cardLicenseKeys = await this.licensesService.issueCardLicenseKeys(
|
||||
payload.userId,
|
||||
userId,
|
||||
body.createCount,
|
||||
);
|
||||
|
||||
@ -154,11 +184,25 @@ export class LicensesController {
|
||||
@Req() req: Request,
|
||||
@Body() body: ActivateCardLicensesRequest,
|
||||
): Promise<ActivateCardLicensesResponse> {
|
||||
const accessToken = retrieveAuthorizationToken(req);
|
||||
const payload = jwt.decode(accessToken, { json: true }) as AccessToken;
|
||||
// TODO strictNullChecks対応
|
||||
const accessToken = retrieveAuthorizationToken(req) as string;
|
||||
if (!accessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000107'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const decodedAccessToken = jwt.decode(accessToken, { json: true });
|
||||
if (!decodedAccessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000101'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const { userId } = decodedAccessToken as AccessToken;
|
||||
|
||||
await this.licensesService.activateCardLicenseKey(
|
||||
payload.userId,
|
||||
userId,
|
||||
body.cardLicenseKey,
|
||||
);
|
||||
|
||||
@ -194,16 +238,27 @@ export class LicensesController {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
@Req() req: Request,
|
||||
): Promise<GetAllocatableLicensesResponse> {
|
||||
const token = retrieveAuthorizationToken(req);
|
||||
const payload = jwt.decode(token, { json: true }) as AccessToken;
|
||||
// TODO strictNullChecks対応
|
||||
const accessToken = retrieveAuthorizationToken(req) as string;
|
||||
if (!accessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000107'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const decodedAccessToken = jwt.decode(accessToken, { json: true });
|
||||
if (!decodedAccessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000101'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const { userId } = decodedAccessToken as AccessToken;
|
||||
|
||||
const context = makeContext(payload.userId);
|
||||
const context = makeContext(userId);
|
||||
|
||||
const allocatableLicenses =
|
||||
await this.licensesService.getAllocatableLicenses(
|
||||
context,
|
||||
payload.userId,
|
||||
);
|
||||
await this.licensesService.getAllocatableLicenses(context, userId);
|
||||
|
||||
return allocatableLicenses;
|
||||
}
|
||||
@ -245,16 +300,26 @@ export class LicensesController {
|
||||
@Req() req: Request,
|
||||
@Body() body: CancelOrderRequest,
|
||||
): Promise<CancelOrderResponse> {
|
||||
const token = retrieveAuthorizationToken(req);
|
||||
const payload = jwt.decode(token, { json: true }) as AccessToken;
|
||||
// TODO strictNullChecks対応
|
||||
const accessToken = retrieveAuthorizationToken(req) as string;
|
||||
if (!accessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000107'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const decodedAccessToken = jwt.decode(accessToken, { json: true });
|
||||
if (!decodedAccessToken) {
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E000101'),
|
||||
HttpStatus.UNAUTHORIZED,
|
||||
);
|
||||
}
|
||||
const { userId } = decodedAccessToken as AccessToken;
|
||||
|
||||
const context = makeContext(payload.userId);
|
||||
const context = makeContext(userId);
|
||||
|
||||
await this.licensesService.cancelOrder(
|
||||
context,
|
||||
payload.userId,
|
||||
body.poNumber,
|
||||
);
|
||||
await this.licensesService.cancelOrder(context, userId, body.poNumber);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,11 +56,11 @@ describe('LicensesService', () => {
|
||||
accountsRepositoryMockValue,
|
||||
);
|
||||
const body = new CreateOrdersRequest();
|
||||
const token: AccessToken = { userId: '0001', role: '', tier: 5 };
|
||||
const userId = '0001';
|
||||
body.orderCount = 1000;
|
||||
body.poNumber = '1';
|
||||
expect(
|
||||
await service.licenseOrders(token, body.poNumber, body.orderCount),
|
||||
await service.licenseOrders(userId, body.poNumber, body.orderCount),
|
||||
).toEqual(undefined);
|
||||
});
|
||||
it('ユーザID取得できなかった場合、エラーとなる', async () => {
|
||||
@ -78,11 +78,11 @@ describe('LicensesService', () => {
|
||||
accountsRepositoryMockValue,
|
||||
);
|
||||
const body = new CreateOrdersRequest();
|
||||
const token: AccessToken = { userId: '', role: '', tier: 5 };
|
||||
const userId = '';
|
||||
body.orderCount = 1000;
|
||||
body.poNumber = '1';
|
||||
await expect(
|
||||
service.licenseOrders(token, body.poNumber, body.orderCount),
|
||||
service.licenseOrders(userId, body.poNumber, body.orderCount),
|
||||
).rejects.toEqual(
|
||||
new HttpException(
|
||||
makeErrorResponse('E009999'),
|
||||
@ -105,11 +105,11 @@ describe('LicensesService', () => {
|
||||
accountsRepositoryMockValue,
|
||||
);
|
||||
const body = new CreateOrdersRequest();
|
||||
const token: AccessToken = { userId: '0001', role: '', tier: 5 };
|
||||
const userId = '0001';
|
||||
body.orderCount = 1000;
|
||||
body.poNumber = '1';
|
||||
await expect(
|
||||
service.licenseOrders(token, body.poNumber, body.orderCount),
|
||||
service.licenseOrders(userId, body.poNumber, body.orderCount),
|
||||
).rejects.toEqual(
|
||||
new HttpException(
|
||||
makeErrorResponse('E009999'),
|
||||
@ -130,11 +130,11 @@ describe('LicensesService', () => {
|
||||
accountsRepositoryMockValue,
|
||||
);
|
||||
const body = new CreateOrdersRequest();
|
||||
const token: AccessToken = { userId: '0001', role: '', tier: 5 };
|
||||
const userId = '0001';
|
||||
body.orderCount = 1000;
|
||||
body.poNumber = '1';
|
||||
await expect(
|
||||
service.licenseOrders(token, body.poNumber, body.orderCount),
|
||||
service.licenseOrders(userId, body.poNumber, body.orderCount),
|
||||
).rejects.toEqual(
|
||||
new HttpException(
|
||||
makeErrorResponse('E010401'),
|
||||
@ -154,7 +154,7 @@ describe('LicensesService', () => {
|
||||
accountsRepositoryMockValue,
|
||||
);
|
||||
const body = new IssueCardLicensesRequest();
|
||||
const token: AccessToken = { userId: '0001', role: '', tier: 5 };
|
||||
const userId = '0001';
|
||||
body.createCount = 10;
|
||||
const issueCardLicensesResponse: IssueCardLicensesResponse = {
|
||||
cardLicenseKeys: [
|
||||
@ -171,7 +171,7 @@ describe('LicensesService', () => {
|
||||
],
|
||||
};
|
||||
expect(
|
||||
await service.issueCardLicenseKeys(token.userId, body.createCount),
|
||||
await service.issueCardLicenseKeys(userId, body.createCount),
|
||||
).toEqual(issueCardLicensesResponse);
|
||||
});
|
||||
it('カードライセンス発行に失敗した場合、エラーになる', async () => {
|
||||
@ -187,10 +187,10 @@ describe('LicensesService', () => {
|
||||
accountsRepositoryMockValue,
|
||||
);
|
||||
const body = new IssueCardLicensesRequest();
|
||||
const token: AccessToken = { userId: '0001', role: '', tier: 5 };
|
||||
const userId = '0001';
|
||||
body.createCount = 1000;
|
||||
await expect(
|
||||
service.issueCardLicenseKeys(token.userId, body.createCount),
|
||||
service.issueCardLicenseKeys(userId, body.createCount),
|
||||
).rejects.toEqual(
|
||||
new HttpException(
|
||||
makeErrorResponse('E009999'),
|
||||
@ -210,10 +210,10 @@ describe('LicensesService', () => {
|
||||
accountsRepositoryMockValue,
|
||||
);
|
||||
const body = new ActivateCardLicensesRequest();
|
||||
const token: AccessToken = { userId: '0001', role: '', tier: 5 };
|
||||
const userId = '0001';
|
||||
body.cardLicenseKey = 'WZCETXC0Z9PQZ9GKRGGY';
|
||||
expect(
|
||||
await service.activateCardLicenseKey(token.userId, body.cardLicenseKey),
|
||||
await service.activateCardLicenseKey(userId, body.cardLicenseKey),
|
||||
).toEqual(undefined);
|
||||
});
|
||||
it('カードライセンス取り込みに失敗した場合、エラーになる(DBエラー)', async () => {
|
||||
@ -229,10 +229,10 @@ describe('LicensesService', () => {
|
||||
accountsRepositoryMockValue,
|
||||
);
|
||||
const body = new ActivateCardLicensesRequest();
|
||||
const token: AccessToken = { userId: '0001', role: '', tier: 5 };
|
||||
const userId = '0001';
|
||||
body.cardLicenseKey = 'WZCETXC0Z9PQZ9GKRGGY';
|
||||
await expect(
|
||||
service.activateCardLicenseKey(token.userId, body.cardLicenseKey),
|
||||
service.activateCardLicenseKey(userId, body.cardLicenseKey),
|
||||
).rejects.toEqual(
|
||||
new HttpException(
|
||||
makeErrorResponse('E009999'),
|
||||
@ -254,10 +254,10 @@ describe('LicensesService', () => {
|
||||
accountsRepositoryMockValue,
|
||||
);
|
||||
const body = new ActivateCardLicensesRequest();
|
||||
const token: AccessToken = { userId: '0001', role: '', tier: 5 };
|
||||
const userId = '0001';
|
||||
body.cardLicenseKey = 'WZCETXC0Z9PQZ9GKRGGY';
|
||||
await expect(
|
||||
service.activateCardLicenseKey(token.userId, body.cardLicenseKey),
|
||||
service.activateCardLicenseKey(userId, body.cardLicenseKey),
|
||||
).rejects.toEqual(
|
||||
new HttpException(makeErrorResponse('E010801'), HttpStatus.BAD_REQUEST),
|
||||
);
|
||||
@ -276,10 +276,10 @@ describe('LicensesService', () => {
|
||||
accountsRepositoryMockValue,
|
||||
);
|
||||
const body = new ActivateCardLicensesRequest();
|
||||
const token: AccessToken = { userId: '0001', role: '', tier: 5 };
|
||||
const userId = '0001';
|
||||
body.cardLicenseKey = 'WZCETXC0Z9PQZ9GKRGGY';
|
||||
await expect(
|
||||
service.activateCardLicenseKey(token.userId, body.cardLicenseKey),
|
||||
service.activateCardLicenseKey(userId, body.cardLicenseKey),
|
||||
).rejects.toEqual(
|
||||
new HttpException(makeErrorResponse('E010802'), HttpStatus.BAD_REQUEST),
|
||||
);
|
||||
@ -287,7 +287,7 @@ describe('LicensesService', () => {
|
||||
});
|
||||
|
||||
describe('DBテスト', () => {
|
||||
let source: DataSource = null;
|
||||
let source: DataSource | null = null;
|
||||
beforeEach(async () => {
|
||||
source = new DataSource({
|
||||
type: 'sqlite',
|
||||
@ -300,12 +300,15 @@ describe('DBテスト', () => {
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
if (!source) return;
|
||||
await source.destroy();
|
||||
source = null;
|
||||
});
|
||||
|
||||
it('カードライセンス発行が完了する(発行数が合っているか確認)', async () => {
|
||||
if (!source) fail();
|
||||
const module = await makeTestingModule(source);
|
||||
if (!module) fail();
|
||||
|
||||
const { id: accountId } = await makeTestSimpleAccount(source);
|
||||
const { external_id: externalId } = await makeTestUser(source, {
|
||||
@ -323,7 +326,9 @@ describe('DBテスト', () => {
|
||||
});
|
||||
|
||||
it('カードライセンス取り込みが完了する', async () => {
|
||||
if (!source) fail();
|
||||
const module = await makeTestingModule(source);
|
||||
if (!module) fail();
|
||||
|
||||
const { id: accountId } = await makeTestSimpleAccount(source);
|
||||
const { external_id: externalId } = await makeTestUser(source, {
|
||||
@ -362,13 +367,15 @@ describe('DBテスト', () => {
|
||||
);
|
||||
const dbSelectResultFromLicense = await selectLicense(source, license_id);
|
||||
expect(
|
||||
dbSelectResultFromCardLicense.cardLicense.activated_at,
|
||||
dbSelectResultFromCardLicense?.cardLicense?.activated_at,
|
||||
).toBeDefined();
|
||||
expect(dbSelectResultFromLicense.license.account_id).toEqual(accountId);
|
||||
expect(dbSelectResultFromLicense?.license?.account_id).toEqual(accountId);
|
||||
});
|
||||
|
||||
it('取込可能なライセンスのみが取得できる', async () => {
|
||||
if (!source) fail();
|
||||
const module = await makeTestingModule(source);
|
||||
if (!module) fail();
|
||||
|
||||
const now = new Date();
|
||||
const { id: accountId } = await makeTestSimpleAccount(source);
|
||||
@ -513,7 +520,7 @@ describe('DBテスト', () => {
|
||||
});
|
||||
|
||||
describe('ライセンス割り当て', () => {
|
||||
let source: DataSource = null;
|
||||
let source: DataSource | null = null;
|
||||
beforeEach(async () => {
|
||||
source = new DataSource({
|
||||
type: 'sqlite',
|
||||
@ -526,12 +533,15 @@ describe('ライセンス割り当て', () => {
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
if (!source) return;
|
||||
await source.destroy();
|
||||
source = null;
|
||||
});
|
||||
|
||||
it('未割当のライセンスに対して、ライセンス割り当てが完了する', async () => {
|
||||
if (!source) fail();
|
||||
const module = await makeTestingModule(source);
|
||||
if (!module) fail();
|
||||
|
||||
const { id: accountId } = await makeTestSimpleAccount(source);
|
||||
const { id: userId } = await makeTestUser(source, {
|
||||
@ -567,11 +577,11 @@ describe('ライセンス割り当て', () => {
|
||||
|
||||
await service.allocateLicense(makeContext('trackingId'), userId, 1);
|
||||
const resultLicense = await selectLicense(source, 1);
|
||||
expect(resultLicense.license.allocated_user_id).toBe(userId);
|
||||
expect(resultLicense.license.status).toBe(
|
||||
expect(resultLicense.license?.allocated_user_id).toBe(userId);
|
||||
expect(resultLicense.license?.status).toBe(
|
||||
LICENSE_ALLOCATED_STATUS.ALLOCATED,
|
||||
);
|
||||
expect(resultLicense.license.expiry_date.setMilliseconds(0)).toEqual(
|
||||
expect(resultLicense.license?.expiry_date?.setMilliseconds(0)).toEqual(
|
||||
expiry_date.setMilliseconds(0),
|
||||
);
|
||||
const licenseAllocationHistory = await selectLicenseAllocationHistory(
|
||||
@ -579,22 +589,24 @@ describe('ライセンス割り当て', () => {
|
||||
userId,
|
||||
1,
|
||||
);
|
||||
expect(licenseAllocationHistory.licenseAllocationHistory.user_id).toBe(
|
||||
expect(licenseAllocationHistory.licenseAllocationHistory?.user_id).toBe(
|
||||
userId,
|
||||
);
|
||||
expect(licenseAllocationHistory.licenseAllocationHistory.license_id).toBe(
|
||||
expect(licenseAllocationHistory.licenseAllocationHistory?.license_id).toBe(
|
||||
1,
|
||||
);
|
||||
expect(licenseAllocationHistory.licenseAllocationHistory.is_allocated).toBe(
|
||||
true,
|
||||
);
|
||||
expect(licenseAllocationHistory.licenseAllocationHistory.account_id).toBe(
|
||||
expect(
|
||||
licenseAllocationHistory.licenseAllocationHistory?.is_allocated,
|
||||
).toBe(true);
|
||||
expect(licenseAllocationHistory.licenseAllocationHistory?.account_id).toBe(
|
||||
accountId,
|
||||
);
|
||||
});
|
||||
|
||||
it('再割り当て可能なライセンスに対して、ライセンス割り当てが完了する', async () => {
|
||||
if (!source) fail();
|
||||
const module = await makeTestingModule(source);
|
||||
if (!module) fail();
|
||||
|
||||
const { id: accountId } = await makeTestSimpleAccount(source);
|
||||
const { id: userId } = await makeTestUser(source, {
|
||||
@ -630,30 +642,32 @@ describe('ライセンス割り当て', () => {
|
||||
|
||||
await service.allocateLicense(makeContext('trackingId'), userId, 1);
|
||||
const result = await selectLicense(source, 1);
|
||||
expect(result.license.allocated_user_id).toBe(userId);
|
||||
expect(result.license.status).toBe(LICENSE_ALLOCATED_STATUS.ALLOCATED);
|
||||
expect(result.license.expiry_date).toEqual(date);
|
||||
expect(result.license?.allocated_user_id).toBe(userId);
|
||||
expect(result.license?.status).toBe(LICENSE_ALLOCATED_STATUS.ALLOCATED);
|
||||
expect(result.license?.expiry_date).toEqual(date);
|
||||
const licenseAllocationHistory = await selectLicenseAllocationHistory(
|
||||
source,
|
||||
userId,
|
||||
1,
|
||||
);
|
||||
expect(licenseAllocationHistory.licenseAllocationHistory.user_id).toBe(
|
||||
expect(licenseAllocationHistory.licenseAllocationHistory?.user_id).toBe(
|
||||
userId,
|
||||
);
|
||||
expect(licenseAllocationHistory.licenseAllocationHistory.license_id).toBe(
|
||||
expect(licenseAllocationHistory.licenseAllocationHistory?.license_id).toBe(
|
||||
1,
|
||||
);
|
||||
expect(licenseAllocationHistory.licenseAllocationHistory.is_allocated).toBe(
|
||||
true,
|
||||
);
|
||||
expect(licenseAllocationHistory.licenseAllocationHistory.account_id).toBe(
|
||||
expect(
|
||||
licenseAllocationHistory.licenseAllocationHistory?.is_allocated,
|
||||
).toBe(true);
|
||||
expect(licenseAllocationHistory.licenseAllocationHistory?.account_id).toBe(
|
||||
accountId,
|
||||
);
|
||||
});
|
||||
|
||||
it('未割当のライセンスに対して、別のライセンスが割り当てられているユーザーの割り当てが完了する', async () => {
|
||||
if (!source) fail();
|
||||
const module = await makeTestingModule(source);
|
||||
if (!module) fail();
|
||||
|
||||
const { id: accountId } = await makeTestSimpleAccount(source);
|
||||
const { id: userId } = await makeTestUser(source, {
|
||||
@ -705,32 +719,32 @@ describe('ライセンス割り当て', () => {
|
||||
|
||||
// もともと割り当てられていたライセンスの状態確認
|
||||
const result1 = await selectLicense(source, 1);
|
||||
expect(result1.license.allocated_user_id).toBe(null);
|
||||
expect(result1.license.status).toBe(LICENSE_ALLOCATED_STATUS.REUSABLE);
|
||||
expect(result1.license.expiry_date).toEqual(date);
|
||||
expect(result1.license?.allocated_user_id).toBe(null);
|
||||
expect(result1.license?.status).toBe(LICENSE_ALLOCATED_STATUS.REUSABLE);
|
||||
expect(result1.license?.expiry_date).toEqual(date);
|
||||
const licenseAllocationHistory = await selectLicenseAllocationHistory(
|
||||
source,
|
||||
userId,
|
||||
1,
|
||||
);
|
||||
expect(licenseAllocationHistory.licenseAllocationHistory.user_id).toBe(
|
||||
expect(licenseAllocationHistory.licenseAllocationHistory?.user_id).toBe(
|
||||
userId,
|
||||
);
|
||||
expect(licenseAllocationHistory.licenseAllocationHistory.license_id).toBe(
|
||||
expect(licenseAllocationHistory.licenseAllocationHistory?.license_id).toBe(
|
||||
1,
|
||||
);
|
||||
expect(licenseAllocationHistory.licenseAllocationHistory.is_allocated).toBe(
|
||||
false,
|
||||
);
|
||||
expect(licenseAllocationHistory.licenseAllocationHistory.account_id).toBe(
|
||||
expect(
|
||||
licenseAllocationHistory.licenseAllocationHistory?.is_allocated,
|
||||
).toBe(false);
|
||||
expect(licenseAllocationHistory.licenseAllocationHistory?.account_id).toBe(
|
||||
accountId,
|
||||
);
|
||||
|
||||
// 新たに割り当てたライセンスの状態確認
|
||||
const result2 = await selectLicense(source, 2);
|
||||
expect(result2.license.allocated_user_id).toBe(userId);
|
||||
expect(result2.license.status).toBe(LICENSE_ALLOCATED_STATUS.ALLOCATED);
|
||||
expect(result2.license.expiry_date.setMilliseconds(0)).toEqual(
|
||||
expect(result2.license?.allocated_user_id).toBe(userId);
|
||||
expect(result2.license?.status).toBe(LICENSE_ALLOCATED_STATUS.ALLOCATED);
|
||||
expect(result2.license?.expiry_date?.setMilliseconds(0)).toEqual(
|
||||
expiry_date.setMilliseconds(0),
|
||||
);
|
||||
const newlicenseAllocationHistory = await selectLicenseAllocationHistory(
|
||||
@ -738,22 +752,24 @@ describe('ライセンス割り当て', () => {
|
||||
userId,
|
||||
2,
|
||||
);
|
||||
expect(newlicenseAllocationHistory.licenseAllocationHistory.user_id).toBe(
|
||||
expect(newlicenseAllocationHistory.licenseAllocationHistory?.user_id).toBe(
|
||||
userId,
|
||||
);
|
||||
expect(
|
||||
newlicenseAllocationHistory.licenseAllocationHistory.license_id,
|
||||
newlicenseAllocationHistory.licenseAllocationHistory?.license_id,
|
||||
).toBe(2);
|
||||
expect(
|
||||
newlicenseAllocationHistory.licenseAllocationHistory.is_allocated,
|
||||
newlicenseAllocationHistory.licenseAllocationHistory?.is_allocated,
|
||||
).toBe(true);
|
||||
expect(
|
||||
newlicenseAllocationHistory.licenseAllocationHistory.account_id,
|
||||
newlicenseAllocationHistory.licenseAllocationHistory?.account_id,
|
||||
).toBe(accountId);
|
||||
});
|
||||
|
||||
it('割り当て時にライセンス履歴テーブルへの登録が完了する(元がNORMALのとき)', async () => {
|
||||
if (!source) fail();
|
||||
const module = await makeTestingModule(source);
|
||||
if (!module) fail();
|
||||
|
||||
const { id: accountId } = await makeTestSimpleAccount(source);
|
||||
const { id: userId } = await makeTestUser(source, {
|
||||
@ -806,12 +822,14 @@ describe('ライセンス割り当て', () => {
|
||||
2,
|
||||
);
|
||||
expect(
|
||||
licenseAllocationHistory.licenseAllocationHistory.switch_from_type,
|
||||
licenseAllocationHistory.licenseAllocationHistory?.switch_from_type,
|
||||
).toBe('NONE');
|
||||
});
|
||||
|
||||
it('割り当て時にライセンス履歴テーブルへの登録が完了する(元がCARDのとき)', async () => {
|
||||
if (!source) fail();
|
||||
const module = await makeTestingModule(source);
|
||||
if (!module) fail();
|
||||
|
||||
const { id: accountId } = await makeTestSimpleAccount(source);
|
||||
const { id: userId } = await makeTestUser(source, {
|
||||
@ -864,12 +882,14 @@ describe('ライセンス割り当て', () => {
|
||||
2,
|
||||
);
|
||||
expect(
|
||||
licenseAllocationHistory.licenseAllocationHistory.switch_from_type,
|
||||
licenseAllocationHistory.licenseAllocationHistory?.switch_from_type,
|
||||
).toBe('CARD');
|
||||
});
|
||||
|
||||
it('割り当て時にライセンス履歴テーブルへの登録が完了する(元がTRIALのとき)', async () => {
|
||||
if (!source) fail();
|
||||
const module = await makeTestingModule(source);
|
||||
if (!module) fail();
|
||||
|
||||
const { id: accountId } = await makeTestSimpleAccount(source);
|
||||
const { id: userId } = await makeTestUser(source, {
|
||||
@ -922,12 +942,14 @@ describe('ライセンス割り当て', () => {
|
||||
2,
|
||||
);
|
||||
expect(
|
||||
licenseAllocationHistory.licenseAllocationHistory.switch_from_type,
|
||||
licenseAllocationHistory.licenseAllocationHistory?.switch_from_type,
|
||||
).toBe('TRIAL');
|
||||
});
|
||||
|
||||
it('有効期限が切れているライセンスを割り当てようとした場合、エラーになる', async () => {
|
||||
if (!source) fail();
|
||||
const module = await makeTestingModule(source);
|
||||
if (!module) fail();
|
||||
|
||||
const { id: accountId } = await makeTestSimpleAccount(source);
|
||||
const { id: userId } = await makeTestUser(source, {
|
||||
@ -961,7 +983,9 @@ describe('ライセンス割り当て', () => {
|
||||
});
|
||||
|
||||
it('割り当て不可なライセンスを割り当てようとした場合、エラーになる', async () => {
|
||||
if (!source) fail();
|
||||
const module = await makeTestingModule(source);
|
||||
if (!module) fail();
|
||||
|
||||
const { id: accountId } = await makeTestSimpleAccount(source);
|
||||
const { id: userId } = await makeTestUser(source, {
|
||||
@ -1013,7 +1037,7 @@ describe('ライセンス割り当て', () => {
|
||||
});
|
||||
|
||||
describe('ライセンス割り当て解除', () => {
|
||||
let source: DataSource = null;
|
||||
let source: DataSource | null = null;
|
||||
beforeEach(async () => {
|
||||
source = new DataSource({
|
||||
type: 'sqlite',
|
||||
@ -1026,12 +1050,15 @@ describe('ライセンス割り当て解除', () => {
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
if (!source) return;
|
||||
await source.destroy();
|
||||
source = null;
|
||||
});
|
||||
|
||||
it('ライセンスの割り当て解除が完了する', async () => {
|
||||
if (!source) fail();
|
||||
const module = await makeTestingModule(source);
|
||||
if (!module) fail();
|
||||
|
||||
const { id: accountId } = await makeTestSimpleAccount(source);
|
||||
const { id: userId } = await makeTestUser(source, {
|
||||
@ -1068,11 +1095,11 @@ describe('ライセンス割り当て解除', () => {
|
||||
|
||||
// 割り当て解除したライセンスの状態確認
|
||||
const deallocatedLicense = await selectLicense(source, 1);
|
||||
expect(deallocatedLicense.license.allocated_user_id).toBe(null);
|
||||
expect(deallocatedLicense.license.status).toBe(
|
||||
expect(deallocatedLicense.license?.allocated_user_id).toBe(null);
|
||||
expect(deallocatedLicense.license?.status).toBe(
|
||||
LICENSE_ALLOCATED_STATUS.REUSABLE,
|
||||
);
|
||||
expect(deallocatedLicense.license.expiry_date).toEqual(date);
|
||||
expect(deallocatedLicense.license?.expiry_date).toEqual(date);
|
||||
|
||||
// ライセンス履歴テーブルの状態確認
|
||||
const licenseAllocationHistory = await selectLicenseAllocationHistory(
|
||||
@ -1080,25 +1107,27 @@ describe('ライセンス割り当て解除', () => {
|
||||
userId,
|
||||
1,
|
||||
);
|
||||
expect(licenseAllocationHistory.licenseAllocationHistory.user_id).toBe(
|
||||
expect(licenseAllocationHistory.licenseAllocationHistory?.user_id).toBe(
|
||||
userId,
|
||||
);
|
||||
expect(licenseAllocationHistory.licenseAllocationHistory.license_id).toBe(
|
||||
expect(licenseAllocationHistory.licenseAllocationHistory?.license_id).toBe(
|
||||
1,
|
||||
);
|
||||
expect(licenseAllocationHistory.licenseAllocationHistory.is_allocated).toBe(
|
||||
false,
|
||||
);
|
||||
expect(licenseAllocationHistory.licenseAllocationHistory.account_id).toBe(
|
||||
expect(
|
||||
licenseAllocationHistory.licenseAllocationHistory?.is_allocated,
|
||||
).toBe(false);
|
||||
expect(licenseAllocationHistory.licenseAllocationHistory?.account_id).toBe(
|
||||
accountId,
|
||||
);
|
||||
expect(
|
||||
licenseAllocationHistory.licenseAllocationHistory.switch_from_type,
|
||||
licenseAllocationHistory.licenseAllocationHistory?.switch_from_type,
|
||||
).toBe('NONE');
|
||||
});
|
||||
|
||||
it('ライセンスが既に割り当て解除されていた場合、エラーとなる', async () => {
|
||||
if (!source) fail();
|
||||
const module = await makeTestingModule(source);
|
||||
if (!module) fail();
|
||||
|
||||
const { id: accountId } = await makeTestSimpleAccount(source);
|
||||
const { id: userId } = await makeTestUser(source, {
|
||||
@ -1158,7 +1187,7 @@ describe('ライセンス割り当て解除', () => {
|
||||
});
|
||||
|
||||
describe('ライセンス注文キャンセル', () => {
|
||||
let source: DataSource = null;
|
||||
let source: DataSource | null = null;
|
||||
beforeEach(async () => {
|
||||
source = new DataSource({
|
||||
type: 'sqlite',
|
||||
@ -1171,12 +1200,15 @@ describe('ライセンス注文キャンセル', () => {
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
if (!source) return;
|
||||
await source.destroy();
|
||||
source = null;
|
||||
});
|
||||
|
||||
it('ライセンス注文のキャンセルが完了する', async () => {
|
||||
if (!source) fail();
|
||||
const module = await makeTestingModule(source);
|
||||
if (!module) fail();
|
||||
const { tier2Accounts: tier2Accounts } = await makeHierarchicalAccounts(
|
||||
source,
|
||||
);
|
||||
@ -1185,7 +1217,7 @@ describe('ライセンス注文キャンセル', () => {
|
||||
source,
|
||||
poNumber,
|
||||
tier2Accounts[0].account.id,
|
||||
tier2Accounts[0].account.parent_account_id,
|
||||
tier2Accounts[0].account.parent_account_id ?? 0,
|
||||
null,
|
||||
10,
|
||||
'Issue Requesting',
|
||||
@ -1195,7 +1227,7 @@ describe('ライセンス注文キャンセル', () => {
|
||||
source,
|
||||
poNumber,
|
||||
tier2Accounts[0].account.id,
|
||||
tier2Accounts[0].account.parent_account_id,
|
||||
tier2Accounts[0].account.parent_account_id ?? 0,
|
||||
null,
|
||||
10,
|
||||
'Order Canceled',
|
||||
@ -1214,12 +1246,14 @@ describe('ライセンス注文キャンセル', () => {
|
||||
tier2Accounts[0].account.id,
|
||||
poNumber,
|
||||
);
|
||||
expect(orderRecord.orderLicense.canceled_at).toBeDefined();
|
||||
expect(orderRecord.orderLicense.status).toBe('Order Canceled');
|
||||
expect(orderRecord.orderLicense?.canceled_at).toBeDefined();
|
||||
expect(orderRecord.orderLicense?.status).toBe('Order Canceled');
|
||||
});
|
||||
|
||||
it('ライセンスが既に発行済みの場合、エラーとなる', async () => {
|
||||
if (!source) fail();
|
||||
const module = await makeTestingModule(source);
|
||||
if (!module) fail();
|
||||
const { tier2Accounts: tier2Accounts } = await makeHierarchicalAccounts(
|
||||
source,
|
||||
);
|
||||
@ -1228,7 +1262,7 @@ describe('ライセンス注文キャンセル', () => {
|
||||
source,
|
||||
poNumber,
|
||||
tier2Accounts[0].account.id,
|
||||
tier2Accounts[0].account.parent_account_id,
|
||||
tier2Accounts[0].account.parent_account_id ?? 0,
|
||||
null,
|
||||
10,
|
||||
'Issued',
|
||||
@ -1247,7 +1281,9 @@ describe('ライセンス注文キャンセル', () => {
|
||||
});
|
||||
|
||||
it('ライセンスが既にキャンセル済みの場合、エラーとなる', async () => {
|
||||
if (!source) fail();
|
||||
const module = await makeTestingModule(source);
|
||||
if (!module) fail();
|
||||
|
||||
const { tier2Accounts: tier2Accounts } = await makeHierarchicalAccounts(
|
||||
source,
|
||||
@ -1257,7 +1293,7 @@ describe('ライセンス注文キャンセル', () => {
|
||||
source,
|
||||
poNumber,
|
||||
tier2Accounts[0].account.id,
|
||||
tier2Accounts[0].account.parent_account_id,
|
||||
tier2Accounts[0].account.parent_account_id ?? 0,
|
||||
null,
|
||||
10,
|
||||
'Order Canceled',
|
||||
|
||||
@ -33,20 +33,20 @@ export class LicensesService {
|
||||
* @param body
|
||||
*/
|
||||
async licenseOrders(
|
||||
accessToken: AccessToken,
|
||||
externalId: string,
|
||||
poNumber: string,
|
||||
orderCount: number,
|
||||
): Promise<void> {
|
||||
//アクセストークンからユーザーIDを取得する
|
||||
this.logger.log(`[IN] ${this.licenseOrders.name}`);
|
||||
const userId = accessToken.userId;
|
||||
let myAccountId: number;
|
||||
let parentAccountId: number;
|
||||
let parentAccountId: number | undefined;
|
||||
|
||||
// ユーザIDからアカウントIDを取得する
|
||||
try {
|
||||
myAccountId = (await this.usersRepository.findUserByExternalId(userId))
|
||||
.account_id;
|
||||
myAccountId = (
|
||||
await this.usersRepository.findUserByExternalId(externalId)
|
||||
).account_id;
|
||||
} catch (e) {
|
||||
this.logger.error(`error=${e}`);
|
||||
switch (e.constructor) {
|
||||
@ -65,9 +65,13 @@ export class LicensesService {
|
||||
|
||||
// 親アカウントIDを取得
|
||||
try {
|
||||
parentAccountId = (
|
||||
await this.accountsRepository.findAccountById(myAccountId)
|
||||
).parent_account_id;
|
||||
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) {
|
||||
|
||||
@ -124,11 +124,11 @@ export const makeDefaultUsersRepositoryMockValue =
|
||||
user1.notification = false;
|
||||
user1.encryption = false;
|
||||
user1.prompt = false;
|
||||
user1.deleted_at = undefined;
|
||||
user1.deleted_at = null;
|
||||
user1.created_by = 'test';
|
||||
user1.created_at = new Date();
|
||||
user1.updated_by = undefined;
|
||||
user1.updated_at = undefined;
|
||||
user1.updated_by = null;
|
||||
user1.updated_at = new Date();
|
||||
|
||||
return {
|
||||
findUserByExternalId: user1,
|
||||
|
||||
@ -12,14 +12,14 @@ import {
|
||||
export const createLicense = async (
|
||||
datasource: DataSource,
|
||||
licenseId: number,
|
||||
expiry_date: Date,
|
||||
expiry_date: Date | null,
|
||||
accountId: number,
|
||||
type: string,
|
||||
status: string,
|
||||
allocated_user_id: number,
|
||||
order_id: number,
|
||||
deleted_at: Date,
|
||||
delete_order_id: number,
|
||||
allocated_user_id: number | null,
|
||||
order_id: number | null,
|
||||
deleted_at: Date | null,
|
||||
delete_order_id: number | null,
|
||||
): Promise<void> => {
|
||||
const { identifiers } = await datasource.getRepository(License).insert({
|
||||
id: licenseId,
|
||||
@ -107,7 +107,7 @@ export const createOrder = async (
|
||||
poNumber: string,
|
||||
fromId: number,
|
||||
toId: number,
|
||||
issuedAt: Date,
|
||||
issuedAt: Date | null,
|
||||
quantity: number,
|
||||
status: string,
|
||||
): Promise<void> => {
|
||||
@ -138,7 +138,7 @@ export const selectCardLicensesCount = async (
|
||||
export const selectCardLicense = async (
|
||||
datasource: DataSource,
|
||||
cardLicenseKey: string,
|
||||
): Promise<{ cardLicense: CardLicense }> => {
|
||||
): Promise<{ cardLicense: CardLicense | null }> => {
|
||||
const cardLicense = await datasource.getRepository(CardLicense).findOne({
|
||||
where: {
|
||||
card_license_key: cardLicenseKey,
|
||||
@ -150,7 +150,7 @@ export const selectCardLicense = async (
|
||||
export const selectLicense = async (
|
||||
datasource: DataSource,
|
||||
id: number,
|
||||
): Promise<{ license: License }> => {
|
||||
): Promise<{ license: License | null }> => {
|
||||
const license = await datasource.getRepository(License).findOne({
|
||||
where: {
|
||||
id: id,
|
||||
@ -163,7 +163,7 @@ export const selectLicenseAllocationHistory = async (
|
||||
datasource: DataSource,
|
||||
userId: number,
|
||||
licence_id: number,
|
||||
): Promise<{ licenseAllocationHistory: LicenseAllocationHistory }> => {
|
||||
): Promise<{ licenseAllocationHistory: LicenseAllocationHistory | null }> => {
|
||||
const licenseAllocationHistory = await datasource
|
||||
.getRepository(LicenseAllocationHistory)
|
||||
.findOne({
|
||||
@ -182,7 +182,7 @@ export const selectOrderLicense = async (
|
||||
datasource: DataSource,
|
||||
accountId: number,
|
||||
poNumber: string,
|
||||
): Promise<{ orderLicense: LicenseOrder }> => {
|
||||
): Promise<{ orderLicense: LicenseOrder | null }> => {
|
||||
const orderLicense = await datasource.getRepository(LicenseOrder).findOne({
|
||||
where: {
|
||||
from_account_id: accountId,
|
||||
|
||||
@ -47,8 +47,8 @@ export class GetAllocatableLicensesRequest {}
|
||||
export class AllocatableLicenseInfo {
|
||||
@ApiProperty()
|
||||
licenseId: number;
|
||||
@ApiProperty()
|
||||
expiryDate: Date;
|
||||
@ApiProperty({ required: false })
|
||||
expiryDate?: Date;
|
||||
}
|
||||
export class GetAllocatableLicensesResponse {
|
||||
@ApiProperty({ type: [AllocatableLicenseInfo] })
|
||||
|
||||
@ -219,6 +219,8 @@ describe('TasksService', () => {
|
||||
audio_format: 'DS',
|
||||
comment: 'comment',
|
||||
is_encrypted: true,
|
||||
deleted_at: null,
|
||||
task: null,
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
@ -263,6 +263,11 @@ export const makeDefaultUserGroupsRepositoryMockValue =
|
||||
user_id: 1,
|
||||
created_by: 'test',
|
||||
updated_by: 'test',
|
||||
created_at: new Date(),
|
||||
deleted_at: null,
|
||||
updated_at: null,
|
||||
user: null,
|
||||
userGroup: null,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
@ -270,6 +275,11 @@ export const makeDefaultUserGroupsRepositoryMockValue =
|
||||
user_id: 2,
|
||||
created_by: 'test',
|
||||
updated_by: 'test',
|
||||
created_at: new Date(),
|
||||
deleted_at: null,
|
||||
updated_at: null,
|
||||
user: null,
|
||||
userGroup: null,
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
@ -277,6 +287,11 @@ export const makeDefaultUserGroupsRepositoryMockValue =
|
||||
user_id: 1,
|
||||
created_by: 'test',
|
||||
updated_by: 'test',
|
||||
created_at: new Date(),
|
||||
deleted_at: null,
|
||||
updated_at: null,
|
||||
user: null,
|
||||
userGroup: null,
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
@ -284,6 +299,11 @@ export const makeDefaultUserGroupsRepositoryMockValue =
|
||||
user_id: 1,
|
||||
created_by: 'test',
|
||||
updated_by: 'test',
|
||||
created_at: new Date(),
|
||||
deleted_at: null,
|
||||
updated_at: null,
|
||||
user: null,
|
||||
userGroup: null,
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
@ -291,6 +311,11 @@ export const makeDefaultUserGroupsRepositoryMockValue =
|
||||
user_id: 3,
|
||||
created_by: 'test',
|
||||
updated_by: 'test',
|
||||
created_at: new Date(),
|
||||
deleted_at: null,
|
||||
updated_at: null,
|
||||
user: null,
|
||||
userGroup: null,
|
||||
},
|
||||
],
|
||||
};
|
||||
@ -343,60 +368,70 @@ const defaultTasksRepositoryMockValue: {
|
||||
audio_file_id: 1,
|
||||
label: 'label01',
|
||||
value: 'value01',
|
||||
task: null,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
audio_file_id: 1,
|
||||
label: 'label02',
|
||||
value: 'value02',
|
||||
task: null,
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
audio_file_id: 1,
|
||||
label: 'label03',
|
||||
value: 'value03',
|
||||
task: null,
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
audio_file_id: 1,
|
||||
label: 'label04',
|
||||
value: 'value04',
|
||||
task: null,
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
audio_file_id: 1,
|
||||
label: 'label05',
|
||||
value: 'value05',
|
||||
task: null,
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
audio_file_id: 1,
|
||||
label: 'label06',
|
||||
value: 'value06',
|
||||
task: null,
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
audio_file_id: 1,
|
||||
label: 'label07',
|
||||
value: 'value07',
|
||||
task: null,
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
audio_file_id: 1,
|
||||
label: 'label08',
|
||||
value: 'value08',
|
||||
task: null,
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
audio_file_id: 1,
|
||||
label: 'label09',
|
||||
value: 'value09',
|
||||
task: null,
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
audio_file_id: 1,
|
||||
label: 'label10',
|
||||
value: 'value10',
|
||||
task: null,
|
||||
},
|
||||
],
|
||||
file: {
|
||||
@ -416,6 +451,8 @@ const defaultTasksRepositoryMockValue: {
|
||||
audio_format: 'DS',
|
||||
comment: 'comment',
|
||||
is_encrypted: true,
|
||||
deleted_at: null,
|
||||
task: null,
|
||||
},
|
||||
},
|
||||
],
|
||||
@ -448,6 +485,9 @@ const defaultTasksRepositoryMockValue: {
|
||||
license: null,
|
||||
userGroupMembers: null,
|
||||
},
|
||||
task: null,
|
||||
user_group_id: null,
|
||||
user_group: null,
|
||||
},
|
||||
],
|
||||
count: 1,
|
||||
|
||||
@ -113,6 +113,7 @@ describe('UsersService.confirmUser', () => {
|
||||
allocated_user_id: resultLicenses[0].allocated_user_id,
|
||||
order_id: resultLicenses[0].order_id,
|
||||
delete_order_id: resultLicenses[0].delete_order_id,
|
||||
user: resultLicenses[0].user ?? null,
|
||||
};
|
||||
|
||||
expect(resultUser.email_verified).toBe(true);
|
||||
@ -126,8 +127,9 @@ describe('UsersService.confirmUser', () => {
|
||||
allocated_user_id: null,
|
||||
order_id: null,
|
||||
delete_order_id: null,
|
||||
user: null,
|
||||
});
|
||||
});
|
||||
}, 600000);
|
||||
|
||||
it('トークンの形式が不正な場合、形式不正エラーとなる。', async () => {
|
||||
if (!source) fail();
|
||||
@ -1762,7 +1764,7 @@ describe('UsersService.getUsers', () => {
|
||||
await expect(service.getUsers('externalId_failed')).rejects.toEqual(
|
||||
new HttpException(makeErrorResponse('E009999'), HttpStatus.NOT_FOUND),
|
||||
);
|
||||
},60000000);
|
||||
}, 60000000);
|
||||
|
||||
it('ADB2Cからのユーザーの取得に失敗した場合、エラーとなる', async () => {
|
||||
const adb2cParam = makeDefaultAdB2cMockValue();
|
||||
|
||||
@ -503,18 +503,27 @@ export class UsersService {
|
||||
|
||||
if (dbUser.license) {
|
||||
// 有効期限日付 YYYY/MM/DD
|
||||
const expiry_date = dbUser.license.expiry_date;
|
||||
expiration = `${expiry_date.getFullYear()}/${
|
||||
expiry_date.getMonth() + 1
|
||||
}/${expiry_date.getDate()}`;
|
||||
const expiry_date = dbUser.license.expiry_date ?? undefined;
|
||||
expiration =
|
||||
expiry_date !== undefined
|
||||
? `${expiry_date.getFullYear()}/${
|
||||
expiry_date.getMonth() + 1
|
||||
}/${expiry_date.getDate()}`
|
||||
: undefined;
|
||||
|
||||
const currentDate = new DateWithZeroTime();
|
||||
// 有効期限までの日数
|
||||
remaining = Math.floor(
|
||||
(expiry_date.getTime() - currentDate.getTime()) /
|
||||
(1000 * 60 * 60 * 24),
|
||||
);
|
||||
if (remaining <= LICENSE_EXPIRATION_THRESHOLD_DAYS) {
|
||||
remaining =
|
||||
expiry_date !== undefined
|
||||
? Math.floor(
|
||||
(expiry_date.getTime() - currentDate.getTime()) /
|
||||
(1000 * 60 * 60 * 24),
|
||||
)
|
||||
: undefined;
|
||||
if (
|
||||
remaining !== undefined &&
|
||||
remaining <= LICENSE_EXPIRATION_THRESHOLD_DAYS
|
||||
) {
|
||||
status = dbUser.auto_renew
|
||||
? USER_LICENSE_STATUS.RENEW
|
||||
: USER_LICENSE_STATUS.ALERT;
|
||||
|
||||
@ -14,7 +14,7 @@ export class Account {
|
||||
id: number;
|
||||
|
||||
@Column({ nullable: true })
|
||||
parent_account_id?: number;
|
||||
parent_account_id: number | null;
|
||||
|
||||
@Column()
|
||||
tier: number;
|
||||
@ -44,7 +44,7 @@ export class Account {
|
||||
active_worktype_id?: number;
|
||||
|
||||
@Column({ nullable: true })
|
||||
deleted_at?: Date;
|
||||
deleted_at: Date | null;
|
||||
|
||||
@Column({ nullable: true })
|
||||
created_by?: string;
|
||||
|
||||
@ -33,11 +33,11 @@ export class AudioFile {
|
||||
@Column()
|
||||
audio_format: string;
|
||||
@Column({ nullable: true })
|
||||
comment?: string;
|
||||
comment: string | null;
|
||||
@Column({ nullable: true })
|
||||
deleted_at?: Date;
|
||||
deleted_at: Date | null;
|
||||
@Column()
|
||||
is_encrypted: boolean;
|
||||
@OneToOne(() => Task, (task) => task.file)
|
||||
task?: Task;
|
||||
task: Task | null;
|
||||
}
|
||||
|
||||
@ -19,5 +19,5 @@ export class AudioOptionItem {
|
||||
value: string;
|
||||
@ManyToOne(() => Task, (task) => task.audio_file_id)
|
||||
@JoinColumn({ name: 'audio_file_id' })
|
||||
task?: Task;
|
||||
task: Task | null;
|
||||
}
|
||||
|
||||
@ -19,20 +19,20 @@ export class CheckoutPermission {
|
||||
task_id: number;
|
||||
|
||||
@Column({ nullable: true })
|
||||
user_id?: number;
|
||||
user_id: number | null;
|
||||
|
||||
@Column({ nullable: true })
|
||||
user_group_id?: number;
|
||||
user_group_id: number | null;
|
||||
|
||||
@OneToOne(() => User, (user) => user.id)
|
||||
@JoinColumn({ name: 'user_id' })
|
||||
user?: User;
|
||||
user: User | null;
|
||||
|
||||
@OneToOne(() => UserGroup, (group) => group.id)
|
||||
@JoinColumn({ name: 'user_group_id' })
|
||||
user_group?: UserGroup;
|
||||
user_group: UserGroup | null;
|
||||
|
||||
@ManyToOne(() => Task, (task) => task.id)
|
||||
@JoinColumn({ name: 'task_id' })
|
||||
task?: Task;
|
||||
task: Task | null;
|
||||
}
|
||||
|
||||
@ -25,11 +25,11 @@ export class LicenseOrder {
|
||||
@Column()
|
||||
to_account_id: number;
|
||||
|
||||
@CreateDateColumn()
|
||||
@CreateDateColumn({ default: () => "datetime('now', 'localtime')" })
|
||||
ordered_at: Date;
|
||||
|
||||
@Column({ nullable: true })
|
||||
issued_at?: Date;
|
||||
issued_at: Date | null;
|
||||
|
||||
@Column()
|
||||
quantity: number;
|
||||
@ -38,18 +38,18 @@ export class LicenseOrder {
|
||||
status: string;
|
||||
|
||||
@Column({ nullable: true })
|
||||
canceled_at?: Date;
|
||||
canceled_at: Date | null;
|
||||
|
||||
@Column({ nullable: true })
|
||||
created_by: string;
|
||||
created_by: string | null;
|
||||
|
||||
@CreateDateColumn()
|
||||
@CreateDateColumn({ default: () => "datetime('now', 'localtime')" })
|
||||
created_at: Date;
|
||||
|
||||
@Column({ nullable: true })
|
||||
updated_by: string;
|
||||
updated_by: string | null;
|
||||
|
||||
@UpdateDateColumn()
|
||||
@UpdateDateColumn({ default: () => "datetime('now', 'localtime')" })
|
||||
updated_at: Date;
|
||||
}
|
||||
|
||||
@ -59,7 +59,7 @@ export class License {
|
||||
id: number;
|
||||
|
||||
@Column({ nullable: true })
|
||||
expiry_date: Date;
|
||||
expiry_date: Date | null;
|
||||
|
||||
@Column()
|
||||
account_id: number;
|
||||
@ -71,34 +71,34 @@ export class License {
|
||||
status: string;
|
||||
|
||||
@Column({ nullable: true })
|
||||
allocated_user_id: number;
|
||||
allocated_user_id: number | null;
|
||||
|
||||
@Column({ nullable: true })
|
||||
order_id: number;
|
||||
order_id: number | null;
|
||||
|
||||
@Column({ nullable: true })
|
||||
deleted_at: Date;
|
||||
deleted_at: Date | null;
|
||||
|
||||
@Column({ nullable: true })
|
||||
delete_order_id: number;
|
||||
delete_order_id: number | null;
|
||||
|
||||
@Column({ nullable: true })
|
||||
created_by: string;
|
||||
created_by: string | null;
|
||||
|
||||
@CreateDateColumn()
|
||||
@CreateDateColumn({ default: () => "datetime('now', 'localtime')" })
|
||||
created_at: Date;
|
||||
|
||||
@Column({ nullable: true })
|
||||
updated_by: string;
|
||||
updated_by: string | null;
|
||||
|
||||
@UpdateDateColumn()
|
||||
@UpdateDateColumn({ default: () => "datetime('now', 'localtime')" })
|
||||
updated_at: Date;
|
||||
|
||||
@OneToOne(() => User, (user) => user.license, {
|
||||
createForeignKeyConstraints: false,
|
||||
}) // createForeignKeyConstraintsはSQLite用設定値.本番用は別途migrationで設定
|
||||
@JoinColumn({ name: 'allocated_user_id' })
|
||||
user?: User;
|
||||
user: User | null;
|
||||
}
|
||||
|
||||
@Entity({ name: 'card_license_issue' })
|
||||
@ -110,15 +110,15 @@ export class CardLicenseIssue {
|
||||
issued_at: Date;
|
||||
|
||||
@Column({ nullable: true })
|
||||
created_by: string;
|
||||
created_by: string | null;
|
||||
|
||||
@CreateDateColumn()
|
||||
@CreateDateColumn({ default: () => "datetime('now', 'localtime')" })
|
||||
created_at: Date;
|
||||
|
||||
@Column({ nullable: true })
|
||||
updated_by: string;
|
||||
updated_by: string | null;
|
||||
|
||||
@UpdateDateColumn()
|
||||
@UpdateDateColumn({ default: () => "datetime('now', 'localtime')" })
|
||||
updated_at: Date;
|
||||
}
|
||||
|
||||
@ -134,18 +134,18 @@ export class CardLicense {
|
||||
card_license_key: string;
|
||||
|
||||
@Column({ nullable: true })
|
||||
activated_at: Date;
|
||||
activated_at: Date | null;
|
||||
|
||||
@Column({ nullable: true })
|
||||
created_by: string;
|
||||
created_by: string | null;
|
||||
|
||||
@CreateDateColumn()
|
||||
@CreateDateColumn({ default: () => "datetime('now', 'localtime')" })
|
||||
created_at: Date;
|
||||
|
||||
@Column({ nullable: true })
|
||||
updated_by: string;
|
||||
updated_by: string | null;
|
||||
|
||||
@UpdateDateColumn({})
|
||||
@UpdateDateColumn({ default: () => "datetime('now', 'localtime')" })
|
||||
updated_at: Date;
|
||||
}
|
||||
|
||||
@ -173,25 +173,25 @@ export class LicenseAllocationHistory {
|
||||
switch_from_type: string;
|
||||
|
||||
@Column({ nullable: true })
|
||||
deleted_at: Date;
|
||||
deleted_at: Date | null;
|
||||
|
||||
@Column({ nullable: true })
|
||||
created_by: string;
|
||||
created_by: string | null;
|
||||
|
||||
@CreateDateColumn()
|
||||
@CreateDateColumn({ default: () => "datetime('now', 'localtime')" })
|
||||
created_at: Date;
|
||||
|
||||
@Column({ nullable: true })
|
||||
updated_by: string;
|
||||
updated_by: string | null;
|
||||
|
||||
@UpdateDateColumn()
|
||||
@UpdateDateColumn({ default: () => "datetime('now', 'localtime')" })
|
||||
updated_at: Date;
|
||||
|
||||
@ManyToOne(() => License, (licenses) => licenses.id, {
|
||||
createForeignKeyConstraints: false,
|
||||
}) // createForeignKeyConstraintsはSQLite用設定値.本番用は別途migrationで設定
|
||||
@JoinColumn({ name: 'license_id' })
|
||||
license?: License;
|
||||
license: License | null;
|
||||
}
|
||||
|
||||
@Entity({ name: 'licenses_archive' })
|
||||
@ -200,7 +200,7 @@ export class LicenseArchive {
|
||||
id: number;
|
||||
|
||||
@Column({ nullable: true })
|
||||
expiry_date: Date;
|
||||
expiry_date: Date | null;
|
||||
|
||||
@Column()
|
||||
account_id: number;
|
||||
@ -212,30 +212,30 @@ export class LicenseArchive {
|
||||
status: string;
|
||||
|
||||
@Column({ nullable: true })
|
||||
allocated_user_id: number;
|
||||
allocated_user_id: number | null;
|
||||
|
||||
@Column({ nullable: true })
|
||||
order_id: number;
|
||||
order_id: number | null;
|
||||
|
||||
@Column({ nullable: true })
|
||||
deleted_at: Date;
|
||||
deleted_at: Date | null;
|
||||
|
||||
@Column({ nullable: true })
|
||||
delete_order_id: number;
|
||||
delete_order_id: number | null;
|
||||
|
||||
@Column({ nullable: true })
|
||||
created_by: string;
|
||||
created_by: string | null;
|
||||
|
||||
@Column()
|
||||
created_at: Date;
|
||||
|
||||
@Column({ nullable: true })
|
||||
updated_by: string;
|
||||
updated_by: string | null;
|
||||
|
||||
@Column()
|
||||
updated_at: Date;
|
||||
|
||||
@CreateDateColumn()
|
||||
@CreateDateColumn({ default: () => "datetime('now', 'localtime')" })
|
||||
archived_at: Date;
|
||||
}
|
||||
|
||||
@ -263,20 +263,20 @@ export class LicenseAllocationHistoryArchive {
|
||||
switch_from_type: string;
|
||||
|
||||
@Column({ nullable: true })
|
||||
deleted_at: Date;
|
||||
deleted_at: Date | null;
|
||||
|
||||
@Column({ nullable: true })
|
||||
created_by: string;
|
||||
created_by: string | null;
|
||||
|
||||
@Column()
|
||||
created_at: Date;
|
||||
|
||||
@Column({ nullable: true })
|
||||
updated_by: string;
|
||||
updated_by: string | null;
|
||||
|
||||
@Column()
|
||||
updated_at: Date;
|
||||
|
||||
@CreateDateColumn()
|
||||
@CreateDateColumn({ default: () => "datetime('now', 'localtime')" })
|
||||
archived_at: Date;
|
||||
}
|
||||
|
||||
@ -444,7 +444,7 @@ export class LicensesRepositoryService {
|
||||
const allocatableLicenses = await queryBuilder.getMany();
|
||||
return allocatableLicenses.map((license) => ({
|
||||
licenseId: license.id,
|
||||
expiryDate: license.expiry_date,
|
||||
expiryDate: license.expiry_date ?? undefined,
|
||||
}));
|
||||
}
|
||||
/**
|
||||
@ -469,6 +469,13 @@ export class LicensesRepositoryService {
|
||||
},
|
||||
});
|
||||
|
||||
// ライセンスが存在しない場合はエラー
|
||||
if (!targetLicense) {
|
||||
throw new LicenseNotExistError(
|
||||
`License not exist. licenseId: ${newLicenseId}`,
|
||||
);
|
||||
}
|
||||
|
||||
// 期限切れの場合はエラー
|
||||
if (targetLicense.expiry_date) {
|
||||
const currentDay = new Date();
|
||||
@ -533,7 +540,7 @@ export class LicensesRepositoryService {
|
||||
});
|
||||
|
||||
let switchFromType = '';
|
||||
if (oldLicenseType) {
|
||||
if (oldLicenseType && oldLicenseType.license) {
|
||||
switch (oldLicenseType.license.type) {
|
||||
case LICENSE_TYPE.CARD:
|
||||
switchFromType = SWITCH_FROM_TYPE.CARD;
|
||||
|
||||
@ -844,8 +844,8 @@ export class TasksRepositoryService {
|
||||
(assignee) => {
|
||||
const checkoutPermission = new CheckoutPermission();
|
||||
checkoutPermission.task_id = taskRecord.id;
|
||||
checkoutPermission.user_id = assignee.typistUserId;
|
||||
checkoutPermission.user_group_id = assignee.typistGroupId;
|
||||
checkoutPermission.user_id = assignee.typistUserId ?? null;
|
||||
checkoutPermission.user_group_id = assignee.typistGroupId ?? null;
|
||||
return checkoutPermission;
|
||||
},
|
||||
);
|
||||
|
||||
@ -20,23 +20,23 @@ export class UserGroup {
|
||||
name: string;
|
||||
|
||||
@Column({ nullable: true })
|
||||
deleted_at?: Date;
|
||||
deleted_at: Date | null;
|
||||
|
||||
@Column({ nullable: true })
|
||||
created_by?: string;
|
||||
created_by: string | null;
|
||||
|
||||
@CreateDateColumn({ default: () => "datetime('now', 'localtime')" }) // defaultはSQLite用設定値.本番用は別途migrationで設定
|
||||
created_at?: Date;
|
||||
created_at: Date | null;
|
||||
|
||||
@Column({ nullable: true })
|
||||
updated_by?: string;
|
||||
updated_by: string | null;
|
||||
|
||||
@UpdateDateColumn({ default: () => "datetime('now', 'localtime')" }) // defaultはSQLite用設定値.本番用は別途migrationで設定
|
||||
updated_at?: Date;
|
||||
updated_at: Date | null;
|
||||
|
||||
@OneToMany(
|
||||
() => UserGroupMember,
|
||||
(userGroupMember) => userGroupMember.userGroup,
|
||||
)
|
||||
userGroupMembers?: UserGroupMember[];
|
||||
userGroupMembers: UserGroupMember[] | null;
|
||||
}
|
||||
|
||||
@ -22,25 +22,25 @@ export class UserGroupMember {
|
||||
user_id: number;
|
||||
|
||||
@Column({ nullable: true })
|
||||
deleted_at?: Date;
|
||||
deleted_at: Date | null;
|
||||
|
||||
@Column({ nullable: true })
|
||||
created_by?: string;
|
||||
created_by: string | null;
|
||||
|
||||
@CreateDateColumn({ default: () => "datetime('now', 'localtime')" }) // defaultはSQLite用設定値.本番用は別途migrationで設定
|
||||
created_at?: Date;
|
||||
created_at: Date | null;
|
||||
|
||||
@Column({ nullable: true })
|
||||
updated_by?: string;
|
||||
updated_by: string | null;
|
||||
|
||||
@UpdateDateColumn({ default: () => "datetime('now', 'localtime')" }) // defaultはSQLite用設定値.本番用は別途migrationで設定
|
||||
updated_at?: Date;
|
||||
updated_at: Date | null;
|
||||
|
||||
@ManyToOne(() => User, (user) => user.id)
|
||||
@JoinColumn({ name: 'user_id' })
|
||||
user?: User;
|
||||
user: User | null;
|
||||
|
||||
@ManyToOne(() => UserGroup, (userGroup) => userGroup.id)
|
||||
@JoinColumn({ name: 'user_group_id' })
|
||||
userGroup?: UserGroup;
|
||||
userGroup: UserGroup | null;
|
||||
}
|
||||
|
||||
@ -19,11 +19,11 @@ export class OptionItem {
|
||||
@Column()
|
||||
initial_value: string;
|
||||
@Column({ nullable: true })
|
||||
created_by?: string;
|
||||
created_by: string | null;
|
||||
@CreateDateColumn({ default: () => "datetime('now', 'localtime')" }) // defaultはSQLite用設定値.本番用は別途migrationで設定
|
||||
created_at?: Date;
|
||||
created_at: Date | null;
|
||||
@Column({ nullable: true })
|
||||
updated_by?: string;
|
||||
updated_by: string | null;
|
||||
@UpdateDateColumn({ default: () => "datetime('now', 'localtime')" }) // defaultはSQLite用設定値.本番用は別途migrationで設定
|
||||
updated_at?: Date;
|
||||
updated_at: Date | null;
|
||||
}
|
||||
|
||||
@ -19,10 +19,10 @@ export class Worktype {
|
||||
custom_worktype_id: string;
|
||||
|
||||
@Column({ nullable: true })
|
||||
description?: string;
|
||||
description: string | null;
|
||||
|
||||
@Column({ nullable: true })
|
||||
deleted_at?: Date;
|
||||
deleted_at: Date | null;
|
||||
|
||||
@Column({ nullable: true })
|
||||
created_by: string;
|
||||
@ -31,7 +31,7 @@ export class Worktype {
|
||||
created_at: Date;
|
||||
|
||||
@Column({ nullable: true })
|
||||
updated_by?: string;
|
||||
updated_by: string | null;
|
||||
|
||||
@UpdateDateColumn({ default: () => "datetime('now', 'localtime')" }) // defaultはSQLite用設定値.本番用は別途migrationで設定
|
||||
updated_at: Date;
|
||||
|
||||
@ -153,7 +153,7 @@ export class WorktypesRepositoryService {
|
||||
|
||||
// ワークタイプを更新
|
||||
worktype.custom_worktype_id = worktypeId;
|
||||
worktype.description = description;
|
||||
worktype.description = description ?? null;
|
||||
await worktypeRepo.save(worktype);
|
||||
});
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user