Merge branch 'develop' into main
This commit is contained in:
commit
409a021cdb
@ -7,9 +7,9 @@
|
|||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "vite",
|
"start": "vite",
|
||||||
"build": "tsc && vite build && cp -r static_contents/. build/",
|
"build": "tsc && vite build",
|
||||||
"build:prod": "tsc && vite build && cp -r static_contents/. build/",
|
"build:prod": "tsc && vite build",
|
||||||
"build:local": "tsc && vite build && cp -r static_contents/. build/ && sh localdeploy.sh",
|
"build:local": "tsc && vite build && sh localdeploy.sh",
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"typecheck": "tsc --noEmit",
|
"typecheck": "tsc --noEmit",
|
||||||
"codegen": "sh codegen.sh",
|
"codegen": "sh codegen.sh",
|
||||||
@ -96,4 +96,4 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1 +0,0 @@
|
|||||||
YOweYATRY5PBN1G9dHDpfWLbSeVvGNpe61DtYdLSC82pqmPNyIw8EHXwTa6o4iNQB5rNSa
|
|
||||||
@ -3792,7 +3792,7 @@
|
|||||||
"properties": { "url": { "type": "string" } },
|
"properties": { "url": { "type": "string" } },
|
||||||
"required": ["url"]
|
"required": ["url"]
|
||||||
},
|
},
|
||||||
"TemplateFile": {
|
"TemplateUploadFinishedRequest": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"name": {
|
"name": {
|
||||||
@ -3801,21 +3801,11 @@
|
|||||||
},
|
},
|
||||||
"url": {
|
"url": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "テンプレートファイルのURL"
|
"description": "テンプレートファイルのアップロード先URL"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["name", "url"]
|
"required": ["name", "url"]
|
||||||
},
|
},
|
||||||
"TemplateUploadFinishedRequest": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"templateFile": {
|
|
||||||
"description": "テンプレートファイルのファイル情報",
|
|
||||||
"allOf": [{ "$ref": "#/components/schemas/TemplateFile" }]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": ["templateFile"]
|
|
||||||
},
|
|
||||||
"TemplateUploadFinishedReqponse": { "type": "object", "properties": {} },
|
"TemplateUploadFinishedReqponse": { "type": "object", "properties": {} },
|
||||||
"Assignee": {
|
"Assignee": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@ -4023,6 +4013,17 @@
|
|||||||
"required": ["poNumber"]
|
"required": ["poNumber"]
|
||||||
},
|
},
|
||||||
"CancelOrderResponse": { "type": "object", "properties": {} },
|
"CancelOrderResponse": { "type": "object", "properties": {} },
|
||||||
|
"TemplateFile": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": { "type": "number", "description": "テンプレートファイルのID" },
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "テンプレートファイルのファイル名"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["id", "name"]
|
||||||
|
},
|
||||||
"GetTemplatesResponse": {
|
"GetTemplatesResponse": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|||||||
@ -30,6 +30,8 @@ import { NotificationhubService } from '../../gateways/notificationhub/notificat
|
|||||||
import { FilesService } from '../../features/files/files.service';
|
import { FilesService } from '../../features/files/files.service';
|
||||||
import { LicensesService } from '../../features/licenses/licenses.service';
|
import { LicensesService } from '../../features/licenses/licenses.service';
|
||||||
import { TasksService } from '../../features/tasks/tasks.service';
|
import { TasksService } from '../../features/tasks/tasks.service';
|
||||||
|
import { TemplatesService } from '../../features/templates/templates.service';
|
||||||
|
import { TemplatesModule } from '../../features/templates/templates.module';
|
||||||
|
|
||||||
export const makeTestingModule = async (
|
export const makeTestingModule = async (
|
||||||
datasource: DataSource,
|
datasource: DataSource,
|
||||||
@ -50,6 +52,7 @@ export const makeTestingModule = async (
|
|||||||
UsersModule,
|
UsersModule,
|
||||||
SendGridModule,
|
SendGridModule,
|
||||||
LicensesModule,
|
LicensesModule,
|
||||||
|
TemplatesModule,
|
||||||
AccountsRepositoryModule,
|
AccountsRepositoryModule,
|
||||||
UsersRepositoryModule,
|
UsersRepositoryModule,
|
||||||
LicensesRepositoryModule,
|
LicensesRepositoryModule,
|
||||||
@ -74,6 +77,7 @@ export const makeTestingModule = async (
|
|||||||
FilesService,
|
FilesService,
|
||||||
TasksService,
|
TasksService,
|
||||||
LicensesService,
|
LicensesService,
|
||||||
|
TemplatesService,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
.useMocker(async (token) => {
|
.useMocker(async (token) => {
|
||||||
|
|||||||
@ -331,13 +331,14 @@ export class FilesController {
|
|||||||
@Req() req: Request,
|
@Req() req: Request,
|
||||||
@Body() body: TemplateUploadFinishedRequest,
|
@Body() body: TemplateUploadFinishedRequest,
|
||||||
): Promise<TemplateUploadFinishedReqponse> {
|
): Promise<TemplateUploadFinishedReqponse> {
|
||||||
const { templateFile } = body;
|
const { name, url } = body;
|
||||||
const token = retrieveAuthorizationToken(req);
|
const token = retrieveAuthorizationToken(req);
|
||||||
const accessToken = jwt.decode(token, { json: true }) as AccessToken;
|
const accessToken = jwt.decode(token, { json: true }) as AccessToken;
|
||||||
|
|
||||||
const context = makeContext(accessToken.userId);
|
const context = makeContext(accessToken.userId);
|
||||||
console.log(context.trackingId);
|
console.log(context.trackingId);
|
||||||
console.log(templateFile);
|
console.log(name);
|
||||||
|
console.log(url);
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
import { TemplateFile } from '../../templates/types/types';
|
|
||||||
|
|
||||||
export class AudioUploadLocationRequest {}
|
export class AudioUploadLocationRequest {}
|
||||||
|
|
||||||
@ -95,8 +94,10 @@ export class AudioUploadFinishedResponse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class TemplateUploadFinishedRequest {
|
export class TemplateUploadFinishedRequest {
|
||||||
@ApiProperty({ description: 'テンプレートファイルのファイル情報' })
|
@ApiProperty({ description: 'テンプレートファイルのファイル名' })
|
||||||
templateFile: TemplateFile;
|
name: string;
|
||||||
|
@ApiProperty({ description: 'テンプレートファイルのアップロード先URL' })
|
||||||
|
url: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class TemplateUploadFinishedReqponse {}
|
export class TemplateUploadFinishedReqponse {}
|
||||||
|
|||||||
@ -47,11 +47,11 @@ export class TemplatesController {
|
|||||||
@Get()
|
@Get()
|
||||||
async getTemplates(@Req() req: Request): Promise<GetTemplatesResponse> {
|
async getTemplates(@Req() req: Request): Promise<GetTemplatesResponse> {
|
||||||
const token = retrieveAuthorizationToken(req);
|
const token = retrieveAuthorizationToken(req);
|
||||||
const accessToken = jwt.decode(token, { json: true }) as AccessToken;
|
const { userId } = jwt.decode(token, { json: true }) as AccessToken;
|
||||||
|
|
||||||
const context = makeContext(accessToken.userId);
|
const context = makeContext(userId);
|
||||||
console.log(context.trackingId);
|
const templates = await this.templatesService.getTemplates(context, userId);
|
||||||
|
|
||||||
return { templates: [] };
|
return { templates };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,11 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { TemplatesController } from './templates.controller';
|
import { TemplatesController } from './templates.controller';
|
||||||
import { TemplatesService } from './templates.service';
|
import { TemplatesService } from './templates.service';
|
||||||
|
import { UsersRepositoryModule } from '../../repositories/users/users.repository.module';
|
||||||
|
import { TemplateFilesRepositoryModule } from '../../repositories/template_files/template_files.repository.module';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [],
|
imports: [UsersRepositoryModule, TemplateFilesRepositoryModule],
|
||||||
providers: [TemplatesService],
|
providers: [TemplatesService],
|
||||||
controllers: [TemplatesController],
|
controllers: [TemplatesController],
|
||||||
})
|
})
|
||||||
|
|||||||
@ -0,0 +1,108 @@
|
|||||||
|
import { DataSource } from 'typeorm';
|
||||||
|
import { makeTestingModule } from '../../common/test/modules';
|
||||||
|
import { TemplatesService } from './templates.service';
|
||||||
|
import { createTemplateFile } from './test/utility';
|
||||||
|
import { makeTestAccount } from '../../common/test/utility';
|
||||||
|
import { makeContext } from '../../common/log';
|
||||||
|
import { TemplateFilesRepositoryService } from '../../repositories/template_files/template_files.repository.service';
|
||||||
|
import { HttpException, HttpStatus } from '@nestjs/common';
|
||||||
|
import { makeErrorResponse } from '../../common/error/makeErrorResponse';
|
||||||
|
|
||||||
|
describe('getTemplates', () => {
|
||||||
|
let source: DataSource = null;
|
||||||
|
beforeEach(async () => {
|
||||||
|
source = new DataSource({
|
||||||
|
type: 'sqlite',
|
||||||
|
database: ':memory:',
|
||||||
|
logging: false,
|
||||||
|
entities: [__dirname + '/../../**/*.entity{.ts,.js}'],
|
||||||
|
synchronize: true, // trueにすると自動的にmigrationが行われるため注意
|
||||||
|
});
|
||||||
|
return source.initialize();
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
await source.destroy();
|
||||||
|
source = null;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('テンプレートファイル一覧を取得できる', async () => {
|
||||||
|
const module = await makeTestingModule(source);
|
||||||
|
const service = module.get<TemplatesService>(TemplatesService);
|
||||||
|
// 第五階層のアカウント作成
|
||||||
|
const { account, admin } = await makeTestAccount(source, { tier: 5 });
|
||||||
|
const context = makeContext(admin.external_id);
|
||||||
|
|
||||||
|
const template1 = await createTemplateFile(
|
||||||
|
source,
|
||||||
|
account.id,
|
||||||
|
'test1',
|
||||||
|
'https://url1/test1',
|
||||||
|
);
|
||||||
|
const template2 = await createTemplateFile(
|
||||||
|
source,
|
||||||
|
account.id,
|
||||||
|
'test2',
|
||||||
|
'https://url2/test2',
|
||||||
|
);
|
||||||
|
|
||||||
|
// 作成したデータを確認
|
||||||
|
{
|
||||||
|
expect(template1.file_name).toBe('test1');
|
||||||
|
expect(template2.file_name).toBe('test2');
|
||||||
|
}
|
||||||
|
|
||||||
|
const templates = await service.getTemplates(context, admin.external_id);
|
||||||
|
|
||||||
|
//実行結果を確認
|
||||||
|
{
|
||||||
|
expect(templates.length).toBe(2);
|
||||||
|
expect(templates[0].id).toBe(template1.id);
|
||||||
|
expect(templates[0].name).toBe(template1.file_name);
|
||||||
|
expect(templates[1].id).toBe(template2.id);
|
||||||
|
expect(templates[1].name).toBe(template2.file_name);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('テンプレートファイル一覧を取得できる(0件)', async () => {
|
||||||
|
const module = await makeTestingModule(source);
|
||||||
|
const service = module.get<TemplatesService>(TemplatesService);
|
||||||
|
// 第五階層のアカウント作成
|
||||||
|
const { admin } = await makeTestAccount(source, { tier: 5 });
|
||||||
|
const context = makeContext(admin.external_id);
|
||||||
|
|
||||||
|
const templates = await service.getTemplates(context, admin.external_id);
|
||||||
|
|
||||||
|
//実行結果を確認
|
||||||
|
{
|
||||||
|
expect(templates.length).toBe(0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('テンプレートファイル一覧の取得に失敗した場合、エラーとなること', async () => {
|
||||||
|
const module = await makeTestingModule(source);
|
||||||
|
const service = module.get<TemplatesService>(TemplatesService);
|
||||||
|
// 第五階層のアカウント作成
|
||||||
|
const { admin } = await makeTestAccount(source, { tier: 5 });
|
||||||
|
const context = makeContext(admin.external_id);
|
||||||
|
|
||||||
|
//DBアクセスに失敗するようにする
|
||||||
|
const typistGroupService = module.get<TemplateFilesRepositoryService>(
|
||||||
|
TemplateFilesRepositoryService,
|
||||||
|
);
|
||||||
|
typistGroupService.getTemplateFiles = jest
|
||||||
|
.fn()
|
||||||
|
.mockRejectedValue('DB failed');
|
||||||
|
|
||||||
|
try {
|
||||||
|
await service.getTemplates(context, admin.external_id);
|
||||||
|
} catch (e) {
|
||||||
|
if (e instanceof HttpException) {
|
||||||
|
expect(e.getStatus()).toEqual(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||||
|
expect(e.getResponse()).toEqual(makeErrorResponse('E009999'));
|
||||||
|
} else {
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -1,7 +1,56 @@
|
|||||||
import { Injectable, Logger } from '@nestjs/common';
|
import { HttpException, HttpStatus, Injectable, Logger } from '@nestjs/common';
|
||||||
|
import { UsersRepositoryService } from '../../repositories/users/users.repository.service';
|
||||||
|
import { TemplateFile } from './types/types';
|
||||||
|
import { Context } from '../../common/log';
|
||||||
|
import { makeErrorResponse } from '../../common/error/makeErrorResponse';
|
||||||
|
import { TemplateFilesRepositoryService } from '../../repositories/template_files/template_files.repository.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class TemplatesService {
|
export class TemplatesService {
|
||||||
private readonly logger = new Logger(TemplatesService.name);
|
private readonly logger = new Logger(TemplatesService.name);
|
||||||
constructor() {}
|
constructor(
|
||||||
|
private readonly usersRepository: UsersRepositoryService,
|
||||||
|
private readonly templateFilesRepository: TemplateFilesRepositoryService,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* アカウント内のテンプレートファイルの一覧を取得する
|
||||||
|
* @param context
|
||||||
|
* @param externalId
|
||||||
|
* @returns templates
|
||||||
|
*/
|
||||||
|
async getTemplates(
|
||||||
|
context: Context,
|
||||||
|
externalId: string,
|
||||||
|
): Promise<TemplateFile[]> {
|
||||||
|
this.logger.log(
|
||||||
|
`[IN] [${context.trackingId}] ${this.getTemplates.name} | params: { externalId: ${externalId} };`,
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { account_id: accountId } =
|
||||||
|
await this.usersRepository.findUserByExternalId(externalId);
|
||||||
|
|
||||||
|
const templateFileRecords =
|
||||||
|
await this.templateFilesRepository.getTemplateFiles(accountId);
|
||||||
|
|
||||||
|
// DBから取得したテンプレートファイルのレコードをレスポンス用に整形する
|
||||||
|
const resTemplates = templateFileRecords.map((templateFile) => ({
|
||||||
|
id: templateFile.id,
|
||||||
|
name: templateFile.file_name,
|
||||||
|
}));
|
||||||
|
|
||||||
|
return resTemplates;
|
||||||
|
} catch (e) {
|
||||||
|
this.logger.error(`error=${e}`);
|
||||||
|
throw new HttpException(
|
||||||
|
makeErrorResponse('E009999'),
|
||||||
|
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||||
|
);
|
||||||
|
} finally {
|
||||||
|
this.logger.log(
|
||||||
|
`[OUT] [${context.trackingId}] ${this.getTemplates.name}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
28
dictation_server/src/features/templates/test/utility.ts
Normal file
28
dictation_server/src/features/templates/test/utility.ts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import { DataSource } from 'typeorm';
|
||||||
|
import { TemplateFile } from '../../../repositories/template_files/entity/template_file.entity';
|
||||||
|
|
||||||
|
export const createTemplateFile = async (
|
||||||
|
datasource: DataSource,
|
||||||
|
accountId: number,
|
||||||
|
name: string,
|
||||||
|
url: string,
|
||||||
|
): Promise<TemplateFile> => {
|
||||||
|
const { identifiers } = await datasource.getRepository(TemplateFile).insert({
|
||||||
|
account_id: accountId,
|
||||||
|
file_name: name,
|
||||||
|
url: url,
|
||||||
|
created_by: 'test_runner',
|
||||||
|
created_at: new Date(),
|
||||||
|
updated_by: 'updater',
|
||||||
|
updated_at: new Date(),
|
||||||
|
});
|
||||||
|
|
||||||
|
const template = identifiers.pop() as TemplateFile;
|
||||||
|
const templateFile = await datasource.getRepository(TemplateFile).findOne({
|
||||||
|
where: {
|
||||||
|
id: template.id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return templateFile;
|
||||||
|
};
|
||||||
@ -1,10 +1,10 @@
|
|||||||
import { ApiProperty } from '@nestjs/swagger';
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
|
|
||||||
export class TemplateFile {
|
export class TemplateFile {
|
||||||
|
@ApiProperty({ description: 'テンプレートファイルのID' })
|
||||||
|
id: number;
|
||||||
@ApiProperty({ description: 'テンプレートファイルのファイル名' })
|
@ApiProperty({ description: 'テンプレートファイルのファイル名' })
|
||||||
name: string;
|
name: string;
|
||||||
@ApiProperty({ description: 'テンプレートファイルのURL' })
|
|
||||||
url: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class GetTemplatesResponse {
|
export class GetTemplatesResponse {
|
||||||
|
|||||||
@ -18,8 +18,6 @@ export class TemplateFile {
|
|||||||
url: string;
|
url: string;
|
||||||
@Column()
|
@Column()
|
||||||
file_name: string;
|
file_name: string;
|
||||||
@Column({ nullable: true })
|
|
||||||
deleted_at?: Date;
|
|
||||||
@Column()
|
@Column()
|
||||||
created_by: string;
|
created_by: string;
|
||||||
@CreateDateColumn()
|
@CreateDateColumn()
|
||||||
|
|||||||
@ -1,7 +1,25 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { DataSource } from 'typeorm';
|
import { DataSource } from 'typeorm';
|
||||||
|
import { TemplateFile } from './entity/template_file.entity';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class TemplateFilesRepositoryService {
|
export class TemplateFilesRepositoryService {
|
||||||
constructor(private dataSource: DataSource) {}
|
constructor(private dataSource: DataSource) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* アカウント内のテンプレートファイルの一覧を取得する
|
||||||
|
* @param accountId
|
||||||
|
* @returns template files
|
||||||
|
*/
|
||||||
|
async getTemplateFiles(accountId: number): Promise<TemplateFile[]> {
|
||||||
|
return await this.dataSource.transaction(async (entityManager) => {
|
||||||
|
const templateFilesRepo = entityManager.getRepository(TemplateFile);
|
||||||
|
|
||||||
|
const templates = await templateFilesRepo.find({
|
||||||
|
where: { account_id: accountId },
|
||||||
|
});
|
||||||
|
|
||||||
|
return templates;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user