Merged PR 458: ワークフロー追加API実装
## 概要 [Task2739: ワークフロー追加API実装](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/2739) - ワークフロー追加APIとテストを実装しました。 ## レビューポイント - リポジトリのチェックロジックは適切か - テストケースは適切か ## UIの変更 - なし ## 動作確認状況 - ローカルで確認
This commit is contained in:
parent
6baeb0b049
commit
c4c2038e6e
@ -56,4 +56,6 @@ export const ErrorCodes = [
|
||||
'E011001', // ワークタイプ重複エラー
|
||||
'E011002', // ワークタイプ登録上限超過エラー
|
||||
'E011003', // ワークタイプ不在エラー
|
||||
'E012001', // テンプレートファイル不在エラー
|
||||
'E013001', // ワークフローのAuthorIDとWorktypeIDのペア重複エラー
|
||||
] as const;
|
||||
|
||||
@ -45,4 +45,6 @@ export const errors: Errors = {
|
||||
E011001: 'This WorkTypeID already used Error',
|
||||
E011002: 'WorkTypeID create limit exceeded Error',
|
||||
E011003: 'WorkTypeID not found Error',
|
||||
E012001: 'Template file not found Error',
|
||||
E013001: 'AuthorId and WorktypeId pair already exists Error',
|
||||
};
|
||||
|
||||
@ -25,7 +25,7 @@ export const createWorkflow = async (
|
||||
return workflow;
|
||||
};
|
||||
|
||||
// Workflowを取得する
|
||||
// Workflow一覧を取得する
|
||||
export const getWorkflows = async (
|
||||
datasource: DataSource,
|
||||
accountId: number,
|
||||
@ -37,6 +37,20 @@ export const getWorkflows = async (
|
||||
});
|
||||
};
|
||||
|
||||
// Workflowを取得する
|
||||
export const getWorkflow = async (
|
||||
datasource: DataSource,
|
||||
accountId: number,
|
||||
id: number,
|
||||
): Promise<Workflow> => {
|
||||
return await datasource.getRepository(Workflow).findOne({
|
||||
where: {
|
||||
account_id: accountId,
|
||||
id: id,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
// Workflowを作成する
|
||||
export const createWorkflowTypist = async (
|
||||
datasource: DataSource,
|
||||
@ -59,3 +73,22 @@ export const createWorkflowTypist = async (
|
||||
|
||||
return workflow;
|
||||
};
|
||||
|
||||
// WorkflowTypist一覧を取得する
|
||||
export const getWorkflowTypists = async (
|
||||
datasource: DataSource,
|
||||
workflowId: number,
|
||||
): Promise<WorkflowTypist[]> => {
|
||||
return await datasource.getRepository(WorkflowTypist).find({
|
||||
where: {
|
||||
workflow_id: workflowId,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
// WorkflowTypist一覧全件を取得する
|
||||
export const getAllWorkflowTypists = async (
|
||||
datasource: DataSource,
|
||||
): Promise<WorkflowTypist[]> => {
|
||||
return await datasource.getRepository(WorkflowTypist).find();
|
||||
};
|
||||
|
||||
@ -104,13 +104,19 @@ export class WorkflowsController {
|
||||
@Req() req: Request,
|
||||
@Body() body: CreateWorkflowsRequest,
|
||||
): Promise<CreateWorkflowsResponse> {
|
||||
const { authorId } = body;
|
||||
const { authorId, worktypeId, templateId, typists } = body;
|
||||
const token = retrieveAuthorizationToken(req);
|
||||
const { userId } = jwt.decode(token, { json: true }) as AccessToken;
|
||||
|
||||
const context = makeContext(userId);
|
||||
console.log(context.trackingId);
|
||||
console.log(authorId);
|
||||
await this.workflowsService.createWorkflow(
|
||||
context,
|
||||
userId,
|
||||
authorId,
|
||||
worktypeId,
|
||||
templateId,
|
||||
typists,
|
||||
);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
@ -9,6 +9,8 @@ import { createWorktype } from '../accounts/test/utility';
|
||||
import {
|
||||
createWorkflow,
|
||||
createWorkflowTypist,
|
||||
getAllWorkflowTypists,
|
||||
getWorkflowTypists,
|
||||
getWorkflows,
|
||||
} from './test/utility';
|
||||
import { createUserGroup } from '../users/test/utility';
|
||||
@ -17,7 +19,7 @@ import { WorkflowsRepositoryService } from '../../repositories/workflows/workflo
|
||||
import { HttpException, HttpStatus } from '@nestjs/common';
|
||||
import { makeErrorResponse } from '../../common/error/makeErrorResponse';
|
||||
|
||||
describe('getWorktypes', () => {
|
||||
describe('getWorkflows', () => {
|
||||
let source: DataSource = null;
|
||||
beforeEach(async () => {
|
||||
source = new DataSource({
|
||||
@ -223,3 +225,703 @@ describe('getWorktypes', () => {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('createWorkflows', () => {
|
||||
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('アカウント内にWorkflowを作成できる(WorktypeIDあり、テンプレートファイルあり)', async () => {
|
||||
const module = await makeTestingModule(source);
|
||||
// 第五階層のアカウント作成
|
||||
const { account, admin } = await makeTestAccount(source, { tier: 5 });
|
||||
const { id: authorId } = await makeTestUser(source, {
|
||||
external_id: 'author1',
|
||||
author_id: 'AUTHOR1',
|
||||
account_id: account.id,
|
||||
role: USER_ROLES.AUTHOR,
|
||||
});
|
||||
const { id: typistId } = await makeTestUser(source, {
|
||||
external_id: 'typist1',
|
||||
account_id: account.id,
|
||||
role: USER_ROLES.TYPIST,
|
||||
});
|
||||
|
||||
const { id: worktypeId } = await createWorktype(
|
||||
source,
|
||||
account.id,
|
||||
'worktype1',
|
||||
);
|
||||
|
||||
const { id: templateId } = await createTemplateFile(
|
||||
source,
|
||||
account.id,
|
||||
'fileName1',
|
||||
'url1',
|
||||
);
|
||||
|
||||
//作成したデータを確認
|
||||
{
|
||||
const workflows = await getWorkflows(source, account.id);
|
||||
const workflowTypists = await getAllWorkflowTypists(source);
|
||||
expect(workflows.length).toBe(0);
|
||||
expect(workflowTypists.length).toBe(0);
|
||||
}
|
||||
|
||||
const service = module.get<WorkflowsService>(WorkflowsService);
|
||||
const context = makeContext(admin.external_id);
|
||||
|
||||
await service.createWorkflow(
|
||||
context,
|
||||
admin.external_id,
|
||||
authorId,
|
||||
worktypeId,
|
||||
templateId,
|
||||
[
|
||||
{
|
||||
typistId: typistId,
|
||||
},
|
||||
],
|
||||
);
|
||||
|
||||
//実行結果を確認
|
||||
{
|
||||
const workflows = await getWorkflows(source, account.id);
|
||||
expect(workflows.length).toBe(1);
|
||||
expect(workflows[0].account_id).toBe(account.id);
|
||||
expect(workflows[0].author_id).toBe(authorId);
|
||||
expect(workflows[0].worktype_id).toBe(worktypeId);
|
||||
expect(workflows[0].template_id).toBe(templateId);
|
||||
|
||||
const workflowTypists = await getWorkflowTypists(source, workflows[0].id);
|
||||
expect(workflowTypists.length).toBe(1);
|
||||
expect(workflowTypists[0].typist_id).toBe(typistId);
|
||||
expect(workflowTypists[0].typist_group_id).toBe(null);
|
||||
}
|
||||
});
|
||||
|
||||
it('アカウント内にWorkflowを作成できる(WorktypeIDなし、テンプレートファイルあり)', async () => {
|
||||
const module = await makeTestingModule(source);
|
||||
// 第五階層のアカウント作成
|
||||
const { account, admin } = await makeTestAccount(source, { tier: 5 });
|
||||
const { id: authorId } = await makeTestUser(source, {
|
||||
external_id: 'author1',
|
||||
author_id: 'AUTHOR1',
|
||||
account_id: account.id,
|
||||
role: USER_ROLES.AUTHOR,
|
||||
});
|
||||
const { id: typistId } = await makeTestUser(source, {
|
||||
external_id: 'typist1',
|
||||
account_id: account.id,
|
||||
role: USER_ROLES.TYPIST,
|
||||
});
|
||||
|
||||
const { id: templateId } = await createTemplateFile(
|
||||
source,
|
||||
account.id,
|
||||
'fileName1',
|
||||
'url1',
|
||||
);
|
||||
|
||||
//作成したデータを確認
|
||||
{
|
||||
const workflows = await getWorkflows(source, account.id);
|
||||
const workflowTypists = await getAllWorkflowTypists(source);
|
||||
expect(workflows.length).toBe(0);
|
||||
expect(workflowTypists.length).toBe(0);
|
||||
}
|
||||
|
||||
const service = module.get<WorkflowsService>(WorkflowsService);
|
||||
const context = makeContext(admin.external_id);
|
||||
|
||||
await service.createWorkflow(
|
||||
context,
|
||||
admin.external_id,
|
||||
authorId,
|
||||
undefined,
|
||||
templateId,
|
||||
[
|
||||
{
|
||||
typistId: typistId,
|
||||
},
|
||||
],
|
||||
);
|
||||
|
||||
//実行結果を確認
|
||||
{
|
||||
const workflows = await getWorkflows(source, account.id);
|
||||
expect(workflows.length).toBe(1);
|
||||
expect(workflows[0].account_id).toBe(account.id);
|
||||
expect(workflows[0].author_id).toBe(authorId);
|
||||
expect(workflows[0].worktype_id).toBe(null);
|
||||
expect(workflows[0].template_id).toBe(templateId);
|
||||
|
||||
const workflowTypists = await getWorkflowTypists(source, workflows[0].id);
|
||||
expect(workflowTypists.length).toBe(1);
|
||||
expect(workflowTypists[0].typist_id).toBe(typistId);
|
||||
expect(workflowTypists[0].typist_group_id).toBe(null);
|
||||
}
|
||||
});
|
||||
|
||||
it('アカウント内にWorkflowを作成できる(WorktypeIDあり、テンプレートファイルなし)', async () => {
|
||||
const module = await makeTestingModule(source);
|
||||
// 第五階層のアカウント作成
|
||||
const { account, admin } = await makeTestAccount(source, { tier: 5 });
|
||||
const { id: authorId } = await makeTestUser(source, {
|
||||
external_id: 'author1',
|
||||
author_id: 'AUTHOR1',
|
||||
account_id: account.id,
|
||||
role: USER_ROLES.AUTHOR,
|
||||
});
|
||||
const { id: typistId } = await makeTestUser(source, {
|
||||
external_id: 'typist1',
|
||||
account_id: account.id,
|
||||
role: USER_ROLES.TYPIST,
|
||||
});
|
||||
|
||||
const { id: worktypeId } = await createWorktype(
|
||||
source,
|
||||
account.id,
|
||||
'worktype1',
|
||||
);
|
||||
|
||||
//作成したデータを確認
|
||||
{
|
||||
const workflows = await getWorkflows(source, account.id);
|
||||
const workflowTypists = await getAllWorkflowTypists(source);
|
||||
expect(workflows.length).toBe(0);
|
||||
expect(workflowTypists.length).toBe(0);
|
||||
}
|
||||
|
||||
const service = module.get<WorkflowsService>(WorkflowsService);
|
||||
const context = makeContext(admin.external_id);
|
||||
|
||||
await service.createWorkflow(
|
||||
context,
|
||||
admin.external_id,
|
||||
authorId,
|
||||
worktypeId,
|
||||
undefined,
|
||||
[
|
||||
{
|
||||
typistId: typistId,
|
||||
},
|
||||
],
|
||||
);
|
||||
|
||||
//実行結果を確認
|
||||
{
|
||||
const workflows = await getWorkflows(source, account.id);
|
||||
expect(workflows.length).toBe(1);
|
||||
expect(workflows[0].account_id).toBe(account.id);
|
||||
expect(workflows[0].author_id).toBe(authorId);
|
||||
expect(workflows[0].worktype_id).toBe(worktypeId);
|
||||
expect(workflows[0].template_id).toBe(null);
|
||||
|
||||
const workflowTypists = await getWorkflowTypists(source, workflows[0].id);
|
||||
expect(workflowTypists.length).toBe(1);
|
||||
expect(workflowTypists[0].typist_id).toBe(typistId);
|
||||
expect(workflowTypists[0].typist_group_id).toBe(null);
|
||||
}
|
||||
});
|
||||
|
||||
it('アカウント内にWorkflowを作成できる(WorktypeIDなし、テンプレートファイルなし)', async () => {
|
||||
const module = await makeTestingModule(source);
|
||||
// 第五階層のアカウント作成
|
||||
const { account, admin } = await makeTestAccount(source, { tier: 5 });
|
||||
const { id: authorId } = await makeTestUser(source, {
|
||||
external_id: 'author1',
|
||||
author_id: 'AUTHOR1',
|
||||
account_id: account.id,
|
||||
role: USER_ROLES.AUTHOR,
|
||||
});
|
||||
const { id: typistId } = await makeTestUser(source, {
|
||||
external_id: 'typist1',
|
||||
account_id: account.id,
|
||||
role: USER_ROLES.TYPIST,
|
||||
});
|
||||
|
||||
//作成したデータを確認
|
||||
{
|
||||
const workflows = await getWorkflows(source, account.id);
|
||||
const workflowTypists = await getAllWorkflowTypists(source);
|
||||
expect(workflows.length).toBe(0);
|
||||
expect(workflowTypists.length).toBe(0);
|
||||
}
|
||||
|
||||
const service = module.get<WorkflowsService>(WorkflowsService);
|
||||
const context = makeContext(admin.external_id);
|
||||
|
||||
await service.createWorkflow(
|
||||
context,
|
||||
admin.external_id,
|
||||
authorId,
|
||||
undefined,
|
||||
undefined,
|
||||
[
|
||||
{
|
||||
typistId: typistId,
|
||||
},
|
||||
],
|
||||
);
|
||||
|
||||
//実行結果を確認
|
||||
{
|
||||
const workflows = await getWorkflows(source, account.id);
|
||||
expect(workflows.length).toBe(1);
|
||||
expect(workflows[0].account_id).toBe(account.id);
|
||||
expect(workflows[0].author_id).toBe(authorId);
|
||||
expect(workflows[0].worktype_id).toBe(null);
|
||||
expect(workflows[0].template_id).toBe(null);
|
||||
|
||||
const workflowTypists = await getWorkflowTypists(source, workflows[0].id);
|
||||
expect(workflowTypists.length).toBe(1);
|
||||
expect(workflowTypists[0].typist_id).toBe(typistId);
|
||||
expect(workflowTypists[0].typist_group_id).toBe(null);
|
||||
}
|
||||
});
|
||||
|
||||
it('DBにAuthorが存在しない場合、400エラーとなること', async () => {
|
||||
const module = await makeTestingModule(source);
|
||||
// 第五階層のアカウント作成
|
||||
const { account, admin } = await makeTestAccount(source, { tier: 5 });
|
||||
|
||||
const { id: typistId } = await makeTestUser(source, {
|
||||
external_id: 'typist1',
|
||||
account_id: account.id,
|
||||
role: USER_ROLES.TYPIST,
|
||||
});
|
||||
|
||||
const { id: worktypeId } = await createWorktype(
|
||||
source,
|
||||
account.id,
|
||||
'worktype1',
|
||||
);
|
||||
|
||||
const { id: templateId } = await createTemplateFile(
|
||||
source,
|
||||
account.id,
|
||||
'fileName1',
|
||||
'url1',
|
||||
);
|
||||
|
||||
//作成したデータを確認
|
||||
{
|
||||
const workflows = await getWorkflows(source, account.id);
|
||||
const workflowTypists = await getAllWorkflowTypists(source);
|
||||
expect(workflows.length).toBe(0);
|
||||
expect(workflowTypists.length).toBe(0);
|
||||
}
|
||||
|
||||
const service = module.get<WorkflowsService>(WorkflowsService);
|
||||
const context = makeContext(admin.external_id);
|
||||
|
||||
//実行結果を確認
|
||||
try {
|
||||
await service.createWorkflow(
|
||||
context,
|
||||
admin.external_id,
|
||||
0,
|
||||
worktypeId,
|
||||
templateId,
|
||||
[
|
||||
{
|
||||
typistId: typistId,
|
||||
},
|
||||
],
|
||||
);
|
||||
} catch (e) {
|
||||
if (e instanceof HttpException) {
|
||||
expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST);
|
||||
expect(e.getResponse()).toEqual(makeErrorResponse('E010204'));
|
||||
} else {
|
||||
fail();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it('DBにWorktypeIDが存在しない場合、400エラーとなること', async () => {
|
||||
const module = await makeTestingModule(source);
|
||||
// 第五階層のアカウント作成
|
||||
const { account, admin } = await makeTestAccount(source, { tier: 5 });
|
||||
const { id: authorId } = await makeTestUser(source, {
|
||||
external_id: 'author1',
|
||||
author_id: 'AUTHOR1',
|
||||
account_id: account.id,
|
||||
role: USER_ROLES.AUTHOR,
|
||||
});
|
||||
const { id: typistId } = await makeTestUser(source, {
|
||||
external_id: 'typist1',
|
||||
account_id: account.id,
|
||||
role: USER_ROLES.TYPIST,
|
||||
});
|
||||
|
||||
const { id: templateId } = await createTemplateFile(
|
||||
source,
|
||||
account.id,
|
||||
'fileName1',
|
||||
'url1',
|
||||
);
|
||||
|
||||
//作成したデータを確認
|
||||
{
|
||||
const workflows = await getWorkflows(source, account.id);
|
||||
const workflowTypists = await getAllWorkflowTypists(source);
|
||||
expect(workflows.length).toBe(0);
|
||||
expect(workflowTypists.length).toBe(0);
|
||||
}
|
||||
|
||||
const service = module.get<WorkflowsService>(WorkflowsService);
|
||||
const context = makeContext(admin.external_id);
|
||||
|
||||
//実行結果を確認
|
||||
try {
|
||||
await service.createWorkflow(
|
||||
context,
|
||||
admin.external_id,
|
||||
authorId,
|
||||
9999,
|
||||
templateId,
|
||||
[
|
||||
{
|
||||
typistId: typistId,
|
||||
},
|
||||
],
|
||||
);
|
||||
} catch (e) {
|
||||
if (e instanceof HttpException) {
|
||||
expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST);
|
||||
expect(e.getResponse()).toEqual(makeErrorResponse('E011003'));
|
||||
} else {
|
||||
fail();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it('DBにテンプレートファイルが存在しない場合、400エラーとなること', async () => {
|
||||
const module = await makeTestingModule(source);
|
||||
// 第五階層のアカウント作成
|
||||
const { account, admin } = await makeTestAccount(source, { tier: 5 });
|
||||
const { id: authorId } = await makeTestUser(source, {
|
||||
external_id: 'author1',
|
||||
author_id: 'AUTHOR1',
|
||||
account_id: account.id,
|
||||
role: USER_ROLES.AUTHOR,
|
||||
});
|
||||
const { id: typistId } = await makeTestUser(source, {
|
||||
external_id: 'typist1',
|
||||
account_id: account.id,
|
||||
role: USER_ROLES.TYPIST,
|
||||
});
|
||||
|
||||
const { id: worktypeId } = await createWorktype(
|
||||
source,
|
||||
account.id,
|
||||
'worktype1',
|
||||
);
|
||||
|
||||
//作成したデータを確認
|
||||
{
|
||||
const workflows = await getWorkflows(source, account.id);
|
||||
const workflowTypists = await getAllWorkflowTypists(source);
|
||||
expect(workflows.length).toBe(0);
|
||||
expect(workflowTypists.length).toBe(0);
|
||||
}
|
||||
|
||||
const service = module.get<WorkflowsService>(WorkflowsService);
|
||||
const context = makeContext(admin.external_id);
|
||||
|
||||
//実行結果を確認
|
||||
try {
|
||||
await service.createWorkflow(
|
||||
context,
|
||||
admin.external_id,
|
||||
authorId,
|
||||
worktypeId,
|
||||
9999,
|
||||
[
|
||||
{
|
||||
typistId: typistId,
|
||||
},
|
||||
],
|
||||
);
|
||||
} catch (e) {
|
||||
if (e instanceof HttpException) {
|
||||
expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST);
|
||||
expect(e.getResponse()).toEqual(makeErrorResponse('E012001'));
|
||||
} else {
|
||||
fail();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it('DBにルーティング候補ユーザーが存在しない場合、400エラーとなること', async () => {
|
||||
const module = await makeTestingModule(source);
|
||||
// 第五階層のアカウント作成
|
||||
const { account, admin } = await makeTestAccount(source, { tier: 5 });
|
||||
const { id: authorId } = await makeTestUser(source, {
|
||||
external_id: 'author1',
|
||||
author_id: 'AUTHOR1',
|
||||
account_id: account.id,
|
||||
role: USER_ROLES.AUTHOR,
|
||||
});
|
||||
|
||||
const { id: worktypeId } = await createWorktype(
|
||||
source,
|
||||
account.id,
|
||||
'worktype1',
|
||||
);
|
||||
|
||||
const { id: templateId } = await createTemplateFile(
|
||||
source,
|
||||
account.id,
|
||||
'fileName1',
|
||||
'url1',
|
||||
);
|
||||
|
||||
//作成したデータを確認
|
||||
{
|
||||
const workflows = await getWorkflows(source, account.id);
|
||||
const workflowTypists = await getAllWorkflowTypists(source);
|
||||
expect(workflows.length).toBe(0);
|
||||
expect(workflowTypists.length).toBe(0);
|
||||
}
|
||||
|
||||
const service = module.get<WorkflowsService>(WorkflowsService);
|
||||
const context = makeContext(admin.external_id);
|
||||
|
||||
//実行結果を確認
|
||||
try {
|
||||
await service.createWorkflow(
|
||||
context,
|
||||
admin.external_id,
|
||||
authorId,
|
||||
worktypeId,
|
||||
templateId,
|
||||
[
|
||||
{
|
||||
typistId: 9999,
|
||||
},
|
||||
],
|
||||
);
|
||||
} catch (e) {
|
||||
if (e instanceof HttpException) {
|
||||
expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST);
|
||||
expect(e.getResponse()).toEqual(makeErrorResponse('E010204'));
|
||||
} else {
|
||||
fail();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it('DBにルーティング候補グループが存在しない場合、400エラーとなること', async () => {
|
||||
const module = await makeTestingModule(source);
|
||||
// 第五階層のアカウント作成
|
||||
const { account, admin } = await makeTestAccount(source, { tier: 5 });
|
||||
const { id: authorId } = await makeTestUser(source, {
|
||||
external_id: 'author1',
|
||||
author_id: 'AUTHOR1',
|
||||
account_id: account.id,
|
||||
role: USER_ROLES.AUTHOR,
|
||||
});
|
||||
|
||||
const { id: worktypeId } = await createWorktype(
|
||||
source,
|
||||
account.id,
|
||||
'worktype1',
|
||||
);
|
||||
|
||||
const { id: templateId } = await createTemplateFile(
|
||||
source,
|
||||
account.id,
|
||||
'fileName1',
|
||||
'url1',
|
||||
);
|
||||
|
||||
//作成したデータを確認
|
||||
{
|
||||
const workflows = await getWorkflows(source, account.id);
|
||||
const workflowTypists = await getAllWorkflowTypists(source);
|
||||
expect(workflows.length).toBe(0);
|
||||
expect(workflowTypists.length).toBe(0);
|
||||
}
|
||||
|
||||
const service = module.get<WorkflowsService>(WorkflowsService);
|
||||
const context = makeContext(admin.external_id);
|
||||
|
||||
//実行結果を確認
|
||||
try {
|
||||
await service.createWorkflow(
|
||||
context,
|
||||
admin.external_id,
|
||||
authorId,
|
||||
worktypeId,
|
||||
templateId,
|
||||
[
|
||||
{
|
||||
typistGroupId: 9999,
|
||||
},
|
||||
],
|
||||
);
|
||||
} catch (e) {
|
||||
if (e instanceof HttpException) {
|
||||
expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST);
|
||||
expect(e.getResponse()).toEqual(makeErrorResponse('E010908'));
|
||||
} else {
|
||||
fail();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it('DBにAuthorIDとWorktypeIDのペアがすでに存在する場合、400エラーとなること', async () => {
|
||||
const module = await makeTestingModule(source);
|
||||
// 第五階層のアカウント作成
|
||||
const { account, admin } = await makeTestAccount(source, { tier: 5 });
|
||||
const { id: authorId } = await makeTestUser(source, {
|
||||
external_id: 'author1',
|
||||
author_id: 'AUTHOR1',
|
||||
account_id: account.id,
|
||||
role: USER_ROLES.AUTHOR,
|
||||
});
|
||||
const { id: typistId } = await makeTestUser(source, {
|
||||
external_id: 'typist1',
|
||||
account_id: account.id,
|
||||
role: USER_ROLES.TYPIST,
|
||||
});
|
||||
|
||||
const { id: worktypeId } = await createWorktype(
|
||||
source,
|
||||
account.id,
|
||||
'worktype1',
|
||||
);
|
||||
|
||||
const { id: templateId } = await createTemplateFile(
|
||||
source,
|
||||
account.id,
|
||||
'fileName1',
|
||||
'url1',
|
||||
);
|
||||
|
||||
await createWorkflow(source, account.id, authorId, worktypeId, templateId);
|
||||
|
||||
//作成したデータを確認
|
||||
{
|
||||
const workflows = await getWorkflows(source, account.id);
|
||||
expect(workflows.length).toBe(1);
|
||||
expect(workflows[0].account_id).toBe(account.id);
|
||||
expect(workflows[0].author_id).toBe(authorId);
|
||||
expect(workflows[0].worktype_id).toBe(worktypeId);
|
||||
expect(workflows[0].template_id).toBe(templateId);
|
||||
}
|
||||
|
||||
const service = module.get<WorkflowsService>(WorkflowsService);
|
||||
const context = makeContext(admin.external_id);
|
||||
|
||||
//実行結果を確認
|
||||
try {
|
||||
await service.createWorkflow(
|
||||
context,
|
||||
admin.external_id,
|
||||
authorId,
|
||||
worktypeId,
|
||||
templateId,
|
||||
[
|
||||
{
|
||||
typistId: typistId,
|
||||
},
|
||||
],
|
||||
);
|
||||
} catch (e) {
|
||||
if (e instanceof HttpException) {
|
||||
expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST);
|
||||
expect(e.getResponse()).toEqual(makeErrorResponse('E013001'));
|
||||
} else {
|
||||
fail();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it('DBアクセスに失敗した場合、500エラーを返却する', async () => {
|
||||
const module = await makeTestingModule(source);
|
||||
// 第五階層のアカウント作成
|
||||
const { account, admin } = await makeTestAccount(source, { tier: 5 });
|
||||
const { id: authorId } = await makeTestUser(source, {
|
||||
external_id: 'author1',
|
||||
author_id: 'AUTHOR1',
|
||||
account_id: account.id,
|
||||
role: USER_ROLES.AUTHOR,
|
||||
});
|
||||
const { id: typistId } = await makeTestUser(source, {
|
||||
external_id: 'typist1',
|
||||
account_id: account.id,
|
||||
role: USER_ROLES.TYPIST,
|
||||
});
|
||||
|
||||
const { id: worktypeId } = await createWorktype(
|
||||
source,
|
||||
account.id,
|
||||
'worktype1',
|
||||
);
|
||||
|
||||
const { id: templateId } = await createTemplateFile(
|
||||
source,
|
||||
account.id,
|
||||
'fileName1',
|
||||
'url1',
|
||||
);
|
||||
|
||||
//作成したデータを確認
|
||||
{
|
||||
const workflows = await getWorkflows(source, account.id);
|
||||
const workflowTypists = await getAllWorkflowTypists(source);
|
||||
expect(workflows.length).toBe(0);
|
||||
expect(workflowTypists.length).toBe(0);
|
||||
}
|
||||
|
||||
const service = module.get<WorkflowsService>(WorkflowsService);
|
||||
const context = makeContext(admin.external_id);
|
||||
|
||||
//DBアクセスに失敗するようにする
|
||||
const templatesService = module.get<WorkflowsRepositoryService>(
|
||||
WorkflowsRepositoryService,
|
||||
);
|
||||
templatesService.createtWorkflows = jest
|
||||
.fn()
|
||||
.mockRejectedValue('DB failed');
|
||||
|
||||
//実行結果を確認
|
||||
try {
|
||||
await service.createWorkflow(
|
||||
context,
|
||||
admin.external_id,
|
||||
authorId,
|
||||
worktypeId,
|
||||
templateId,
|
||||
[
|
||||
{
|
||||
typistId: typistId,
|
||||
},
|
||||
],
|
||||
);
|
||||
} catch (e) {
|
||||
if (e instanceof HttpException) {
|
||||
expect(e.getStatus()).toEqual(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
expect(e.getResponse()).toEqual(makeErrorResponse('E009999'));
|
||||
} else {
|
||||
fail();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,9 +1,15 @@
|
||||
import { HttpException, HttpStatus, Injectable, Logger } from '@nestjs/common';
|
||||
import { makeErrorResponse } from '../../common/error/makeErrorResponse';
|
||||
import { Context } from '../../common/log';
|
||||
import { Workflow } from './types/types';
|
||||
import { UsersRepositoryService } from '../../repositories/users/users.repository.service';
|
||||
import { WorkflowsRepositoryService } from '../../repositories/workflows/workflows.repository.service';
|
||||
import { UsersRepositoryService } from '../../repositories/users/users.repository.service';
|
||||
import { WorkflowTypist } from './types/types';
|
||||
import { Context } from '../../common/log';
|
||||
import { makeErrorResponse } from '../../common/error/makeErrorResponse';
|
||||
import { UserNotFoundError } from '../../repositories/users/errors/types';
|
||||
import { TypistGroupNotExistError } from '../../repositories/user_groups/errors/types';
|
||||
import { WorktypeIdNotFoundError } from '../../repositories/worktypes/errors/types';
|
||||
import { TemplateFileNotExistError } from '../../repositories/template_files/errors/types';
|
||||
import { AuthorIdAndWorktypeIdPairAlreadyExistsError } from '../../repositories/workflows/errors/types';
|
||||
import { Workflow } from './types/types';
|
||||
import { AdB2cService } from '../../gateways/adb2c/adb2c.service';
|
||||
|
||||
@Injectable()
|
||||
@ -106,4 +112,88 @@ export class WorkflowsService {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ワークフローを作成する
|
||||
* @param context
|
||||
* @param externalId
|
||||
* @param authorId
|
||||
* @param worktypeId
|
||||
* @param templateId
|
||||
* @param typists
|
||||
* @returns workflow
|
||||
*/
|
||||
async createWorkflow(
|
||||
context: Context,
|
||||
externalId: string,
|
||||
authorId: number,
|
||||
worktypeId?: number | undefined,
|
||||
templateId?: number | undefined,
|
||||
typists?: WorkflowTypist[],
|
||||
): Promise<void> {
|
||||
this.logger.log(
|
||||
`[IN] [${context.trackingId}] ${this.createWorkflow.name} | | params: { ` +
|
||||
`externalId: ${externalId}, ` +
|
||||
`authorId: ${authorId}, ` +
|
||||
`worktypeId: ${worktypeId}, ` +
|
||||
`templateId: ${templateId}, ` +
|
||||
`typists: ${JSON.stringify(typists)} };`,
|
||||
);
|
||||
try {
|
||||
const { account_id: accountId } =
|
||||
await this.usersRepository.findUserByExternalId(externalId);
|
||||
|
||||
await this.workflowsRepository.createtWorkflows(
|
||||
accountId,
|
||||
authorId,
|
||||
worktypeId,
|
||||
templateId,
|
||||
typists,
|
||||
);
|
||||
} catch (e) {
|
||||
this.logger.error(`[${context.trackingId}] error=${e}`);
|
||||
if (e instanceof Error) {
|
||||
switch (e.constructor) {
|
||||
case UserNotFoundError:
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E010204'),
|
||||
HttpStatus.BAD_REQUEST,
|
||||
);
|
||||
case TypistGroupNotExistError:
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E010908'),
|
||||
HttpStatus.BAD_REQUEST,
|
||||
);
|
||||
case WorktypeIdNotFoundError:
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E011003'),
|
||||
HttpStatus.BAD_REQUEST,
|
||||
);
|
||||
case TemplateFileNotExistError:
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E012001'),
|
||||
HttpStatus.BAD_REQUEST,
|
||||
);
|
||||
case AuthorIdAndWorktypeIdPairAlreadyExistsError:
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E013001'),
|
||||
HttpStatus.BAD_REQUEST,
|
||||
);
|
||||
default:
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E009999'),
|
||||
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||
);
|
||||
}
|
||||
}
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E009999'),
|
||||
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||
);
|
||||
} finally {
|
||||
this.logger.log(
|
||||
`[OUT] [${context.trackingId}] ${this.createWorkflow.name}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,2 @@
|
||||
// テンプレートファイルが存在しないエラー
|
||||
export class TemplateFileNotExistError extends Error {}
|
||||
@ -0,0 +1,2 @@
|
||||
// AuthorIDとWorktypeIDのペア重複エラー
|
||||
export class AuthorIdAndWorktypeIdPairAlreadyExistsError extends Error {}
|
||||
@ -1,6 +1,17 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { DataSource } from 'typeorm';
|
||||
import { DataSource, In } from 'typeorm';
|
||||
import { Workflow } from './entity/workflow.entity';
|
||||
import { WorkflowTypist as DbWorkflowTypist } from './entity/workflow_typists.entity';
|
||||
import { User } from '../users/entity/user.entity';
|
||||
import { WorkflowTypist } from '../../features/workflows/types/types';
|
||||
import { Worktype } from '../worktypes/entity/worktype.entity';
|
||||
import { TemplateFile } from '../template_files/entity/template_file.entity';
|
||||
import { UserGroup } from '../user_groups/entity/user_group.entity';
|
||||
import { TypistGroupNotExistError } from '../user_groups/errors/types';
|
||||
import { UserNotFoundError } from '../users/errors/types';
|
||||
import { WorktypeIdNotFoundError } from '../worktypes/errors/types';
|
||||
import { TemplateFileNotExistError } from '../template_files/errors/types';
|
||||
import { AuthorIdAndWorktypeIdPairAlreadyExistsError } from './errors/types';
|
||||
|
||||
@Injectable()
|
||||
export class WorkflowsRepositoryService {
|
||||
@ -31,4 +42,162 @@ export class WorkflowsRepositoryService {
|
||||
return workflows;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* ワークフローを作成する
|
||||
* @param accountId
|
||||
* @param authorId
|
||||
* @param worktypeId
|
||||
* @param templateId
|
||||
* @param typists
|
||||
* @returns workflows
|
||||
*/
|
||||
async createtWorkflows(
|
||||
accountId: number,
|
||||
authorId: number,
|
||||
worktypeId?: number | undefined,
|
||||
templateId?: number | undefined,
|
||||
typists?: WorkflowTypist[],
|
||||
): Promise<void> {
|
||||
return await this.dataSource.transaction(async (entityManager) => {
|
||||
// authorの存在確認
|
||||
const userRepo = entityManager.getRepository(User);
|
||||
const author = await userRepo.findOne({
|
||||
where: { account_id: accountId, id: authorId },
|
||||
});
|
||||
if (!author) {
|
||||
throw new UserNotFoundError(`author not found. id: ${authorId}`);
|
||||
}
|
||||
|
||||
// worktypeの存在確認
|
||||
if (worktypeId !== undefined) {
|
||||
const worktypeRepo = entityManager.getRepository(Worktype);
|
||||
const worktypes = await worktypeRepo.find({
|
||||
where: { account_id: accountId, id: worktypeId },
|
||||
});
|
||||
if (worktypes.length === 0) {
|
||||
throw new WorktypeIdNotFoundError(
|
||||
`worktype not found. id: ${worktypeId}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// templateの存在確認
|
||||
if (templateId !== undefined) {
|
||||
const templateRepo = entityManager.getRepository(TemplateFile);
|
||||
const template = await templateRepo.findOne({
|
||||
where: { account_id: accountId, id: templateId },
|
||||
});
|
||||
if (!template) {
|
||||
throw new TemplateFileNotExistError('template not found');
|
||||
}
|
||||
}
|
||||
|
||||
// ルーティング候補ユーザーの存在確認
|
||||
const typistIds = typists.flatMap((typist) =>
|
||||
typist.typistId ? [typist.typistId] : [],
|
||||
);
|
||||
const typistUsers = await userRepo.find({
|
||||
where: { account_id: accountId, id: In(typistIds) },
|
||||
});
|
||||
if (typistUsers.length !== typistIds.length) {
|
||||
throw new UserNotFoundError(`typist not found. ids: ${typistIds}`);
|
||||
}
|
||||
|
||||
// ルーティング候補ユーザーグループの存在確認
|
||||
const groupIds = typists.flatMap((typist) => {
|
||||
return typist.typistGroupId ? [typist.typistGroupId] : [];
|
||||
});
|
||||
const userGroupRepo = entityManager.getRepository(UserGroup);
|
||||
const typistGroups = await userGroupRepo.find({
|
||||
where: { account_id: accountId, id: In(groupIds) },
|
||||
});
|
||||
if (typistGroups.length !== groupIds.length) {
|
||||
throw new TypistGroupNotExistError(
|
||||
`typist group not found. ids: ${groupIds}`,
|
||||
);
|
||||
}
|
||||
|
||||
const workflowRepo = entityManager.getRepository(Workflow);
|
||||
|
||||
// ワークフローの重複確認
|
||||
const workflow = await workflowRepo.find({
|
||||
where: {
|
||||
account_id: accountId,
|
||||
author_id: authorId,
|
||||
worktype_id: worktypeId,
|
||||
},
|
||||
});
|
||||
if (workflow.length !== 0) {
|
||||
throw new AuthorIdAndWorktypeIdPairAlreadyExistsError(
|
||||
'workflow already exists',
|
||||
);
|
||||
}
|
||||
|
||||
// ワークフローのデータ作成
|
||||
const newWorkflow = this.makeWorkflow(
|
||||
accountId,
|
||||
authorId,
|
||||
worktypeId,
|
||||
templateId,
|
||||
);
|
||||
|
||||
await workflowRepo.save(newWorkflow);
|
||||
|
||||
// ルーティング候補のデータ作成
|
||||
const workflowTypists = typists.map((typist) =>
|
||||
this.makeWorkflowTypist(
|
||||
newWorkflow.id,
|
||||
typist.typistId,
|
||||
typist.typistGroupId,
|
||||
),
|
||||
);
|
||||
|
||||
const workflowTypistsRepo = entityManager.getRepository(DbWorkflowTypist);
|
||||
await workflowTypistsRepo.save(workflowTypists);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* DBに保存するワークフローデータを作成する
|
||||
* @param accountId
|
||||
* @param authorId
|
||||
* @param worktypeId
|
||||
* @param templateId
|
||||
* @returns workflow
|
||||
*/
|
||||
private makeWorkflow(
|
||||
accountId: number,
|
||||
authorId: number,
|
||||
worktypeId?: number | undefined,
|
||||
templateId?: number | undefined,
|
||||
): Workflow {
|
||||
const workflow = new Workflow();
|
||||
workflow.account_id = accountId;
|
||||
workflow.author_id = authorId;
|
||||
workflow.worktype_id = worktypeId;
|
||||
workflow.template_id = templateId;
|
||||
|
||||
return workflow;
|
||||
}
|
||||
|
||||
/**
|
||||
* DBに保存するルーティング候補データを作成する
|
||||
* @param workflowId
|
||||
* @param typistId
|
||||
* @param typistGroupId
|
||||
* @returns workflow typist
|
||||
*/
|
||||
private makeWorkflowTypist(
|
||||
workflowId: number,
|
||||
typistId: number,
|
||||
typistGroupId: number,
|
||||
): DbWorkflowTypist {
|
||||
const workflowTypist = new DbWorkflowTypist();
|
||||
workflowTypist.workflow_id = workflowId;
|
||||
workflowTypist.typist_id = typistId;
|
||||
workflowTypist.typist_group_id = typistGroupId;
|
||||
|
||||
return workflowTypist;
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user