Merged PR 465: API実装(ワークフロー更新API)

## 概要
[Task2776: API実装(ワークフロー更新API)](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/2776)

- ワークフロー編集APIとテストを実装しました。

## レビューポイント
- リポジトリでのチェック処理は適切か
- テストケースは適切か

## UIの変更
- なし

## 動作確認状況
- ローカルで確認
This commit is contained in:
makabe.t 2023-10-06 00:10:47 +00:00
parent 983726eaf3
commit f70e266e85
7 changed files with 1152 additions and 10 deletions

View File

@ -58,4 +58,5 @@ export const ErrorCodes = [
'E011003', // ワークタイプ不在エラー
'E012001', // テンプレートファイル不在エラー
'E013001', // ワークフローのAuthorIDとWorktypeIDのペア重複エラー
'E013002', // ワークフロー不在エラー
] as const;

View File

@ -47,4 +47,5 @@ export const errors: Errors = {
E011003: 'WorkTypeID not found Error',
E012001: 'Template file not found Error',
E013001: 'AuthorId and WorktypeId pair already exists Error',
E013002: 'Workflow not found Error',
};

View File

@ -156,16 +156,21 @@ export class WorkflowsController {
@Param() param: UpdateWorkflowRequestParam,
@Body() body: UpdateWorkflowRequest,
): Promise<UpdateWorkflowResponse> {
const { authorId } = body;
const { authorId, worktypeId, templateId, typists } = body;
const { workflowId } = param;
const token = retrieveAuthorizationToken(req);
const { userId } = jwt.decode(token, { json: true }) as AccessToken;
console.log('updateWorkflow');
const context = makeContext(userId);
console.log(context.trackingId);
console.log(authorId);
console.log(workflowId);
await this.workflowsService.updateWorkflow(
context,
userId,
workflowId,
authorId,
worktypeId,
templateId,
typists,
);
return {};
}

View File

@ -925,3 +925,900 @@ describe('createWorkflows', () => {
}
});
});
describe('updateWorkflow', () => {
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: authorId1 } = await makeTestUser(source, {
external_id: 'author1',
author_id: 'AUTHOR1',
account_id: account.id,
role: USER_ROLES.AUTHOR,
});
const { id: authorId2 } = await makeTestUser(source, {
external_id: 'author2',
author_id: 'AUTHOR2',
account_id: account.id,
role: USER_ROLES.AUTHOR,
});
const { id: typistId1 } = await makeTestUser(source, {
external_id: 'typist1',
account_id: account.id,
role: USER_ROLES.TYPIST,
});
const { id: typistId2 } = await makeTestUser(source, {
external_id: 'typist12',
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 preWorkflow = await createWorkflow(
source,
account.id,
authorId1,
undefined,
undefined,
);
await createWorkflowTypist(source, preWorkflow.id, typistId1);
//作成したデータを確認
{
const workflows = await getWorkflows(source, account.id);
const workflowTypists = await getAllWorkflowTypists(source);
expect(workflows.length).toBe(1);
expect(workflows[0].id).toBe(preWorkflow.id);
expect(workflows[0].account_id).toBe(account.id);
expect(workflows[0].author_id).toBe(authorId1);
expect(workflows[0].worktype_id).toBe(null);
expect(workflows[0].template_id).toBe(null);
expect(workflowTypists.length).toBe(1);
}
const service = module.get<WorkflowsService>(WorkflowsService);
const context = makeContext(admin.external_id);
await service.updateWorkflow(
context,
admin.external_id,
preWorkflow.id,
authorId2,
worktypeId,
templateId,
[
{
typistId: typistId2,
},
],
);
//実行結果を確認
{
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(authorId2);
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(typistId2);
}
});
it('アカウント内にWorkflowを作成できるWorktypeIDなし、テンプレートファイルあり', async () => {
const module = await makeTestingModule(source);
// 第五階層のアカウント作成
const { account, admin } = await makeTestAccount(source, { tier: 5 });
const { id: authorId1 } = await makeTestUser(source, {
external_id: 'author1',
author_id: 'AUTHOR1',
account_id: account.id,
role: USER_ROLES.AUTHOR,
});
const { id: authorId2 } = await makeTestUser(source, {
external_id: 'author2',
author_id: 'AUTHOR2',
account_id: account.id,
role: USER_ROLES.AUTHOR,
});
const { id: typistId1 } = await makeTestUser(source, {
external_id: 'typist1',
account_id: account.id,
role: USER_ROLES.TYPIST,
});
const { id: typistId2 } = await makeTestUser(source, {
external_id: 'typist12',
account_id: account.id,
role: USER_ROLES.TYPIST,
});
const { id: templateId } = await createTemplateFile(
source,
account.id,
'fileName1',
'url1',
);
const preWorkflow = await createWorkflow(
source,
account.id,
authorId1,
undefined,
undefined,
);
await createWorkflowTypist(source, preWorkflow.id, typistId1);
//作成したデータを確認
{
const workflows = await getWorkflows(source, account.id);
const workflowTypists = await getAllWorkflowTypists(source);
expect(workflows.length).toBe(1);
expect(workflows[0].id).toBe(preWorkflow.id);
expect(workflows[0].account_id).toBe(account.id);
expect(workflows[0].author_id).toBe(authorId1);
expect(workflows[0].worktype_id).toBe(null);
expect(workflows[0].template_id).toBe(null);
expect(workflowTypists.length).toBe(1);
}
const service = module.get<WorkflowsService>(WorkflowsService);
const context = makeContext(admin.external_id);
await service.updateWorkflow(
context,
admin.external_id,
preWorkflow.id,
authorId2,
undefined,
templateId,
[
{
typistId: typistId2,
},
],
);
//実行結果を確認
{
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(authorId2);
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(typistId2);
}
});
it('アカウント内にWorkflowを作成できるWorktypeIDあり、テンプレートファイルなし', async () => {
const module = await makeTestingModule(source);
// 第五階層のアカウント作成
const { account, admin } = await makeTestAccount(source, { tier: 5 });
const { id: authorId1 } = await makeTestUser(source, {
external_id: 'author1',
author_id: 'AUTHOR1',
account_id: account.id,
role: USER_ROLES.AUTHOR,
});
const { id: authorId2 } = await makeTestUser(source, {
external_id: 'author2',
author_id: 'AUTHOR2',
account_id: account.id,
role: USER_ROLES.AUTHOR,
});
const { id: typistId1 } = await makeTestUser(source, {
external_id: 'typist1',
account_id: account.id,
role: USER_ROLES.TYPIST,
});
const { id: typistId2 } = await makeTestUser(source, {
external_id: 'typist12',
account_id: account.id,
role: USER_ROLES.TYPIST,
});
const { id: worktypeId } = await createWorktype(
source,
account.id,
'worktype1',
);
const preWorkflow = await createWorkflow(
source,
account.id,
authorId1,
undefined,
undefined,
);
await createWorkflowTypist(source, preWorkflow.id, typistId1);
//作成したデータを確認
{
const workflows = await getWorkflows(source, account.id);
const workflowTypists = await getAllWorkflowTypists(source);
expect(workflows.length).toBe(1);
expect(workflows[0].id).toBe(preWorkflow.id);
expect(workflows[0].account_id).toBe(account.id);
expect(workflows[0].author_id).toBe(authorId1);
expect(workflows[0].worktype_id).toBe(null);
expect(workflows[0].template_id).toBe(null);
expect(workflowTypists.length).toBe(1);
}
const service = module.get<WorkflowsService>(WorkflowsService);
const context = makeContext(admin.external_id);
await service.updateWorkflow(
context,
admin.external_id,
preWorkflow.id,
authorId2,
worktypeId,
undefined,
[
{
typistId: typistId2,
},
],
);
//実行結果を確認
{
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(authorId2);
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(typistId2);
}
});
it('アカウント内にWorkflowを作成できるWorktypeIDなし、テンプレートファイルなし', async () => {
const module = await makeTestingModule(source);
// 第五階層のアカウント作成
const { account, admin } = await makeTestAccount(source, { tier: 5 });
const { id: authorId1 } = await makeTestUser(source, {
external_id: 'author1',
author_id: 'AUTHOR1',
account_id: account.id,
role: USER_ROLES.AUTHOR,
});
const { id: authorId2 } = await makeTestUser(source, {
external_id: 'author2',
author_id: 'AUTHOR2',
account_id: account.id,
role: USER_ROLES.AUTHOR,
});
const { id: typistId1 } = await makeTestUser(source, {
external_id: 'typist1',
account_id: account.id,
role: USER_ROLES.TYPIST,
});
const { id: typistId2 } = await makeTestUser(source, {
external_id: 'typist12',
account_id: account.id,
role: USER_ROLES.TYPIST,
});
const preWorkflow = await createWorkflow(
source,
account.id,
authorId1,
undefined,
undefined,
);
await createWorkflowTypist(source, preWorkflow.id, typistId1);
//作成したデータを確認
{
const workflows = await getWorkflows(source, account.id);
const workflowTypists = await getAllWorkflowTypists(source);
expect(workflows.length).toBe(1);
expect(workflows[0].id).toBe(preWorkflow.id);
expect(workflows[0].account_id).toBe(account.id);
expect(workflows[0].author_id).toBe(authorId1);
expect(workflows[0].worktype_id).toBe(null);
expect(workflows[0].template_id).toBe(null);
expect(workflowTypists.length).toBe(1);
}
const service = module.get<WorkflowsService>(WorkflowsService);
const context = makeContext(admin.external_id);
await service.updateWorkflow(
context,
admin.external_id,
preWorkflow.id,
authorId2,
undefined,
undefined,
[
{
typistId: typistId2,
},
],
);
//実行結果を確認
{
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(authorId2);
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(typistId2);
}
});
it('DBにWorkflowが存在しない場合、400エラーとなること', async () => {
const module = await makeTestingModule(source);
// 第五階層のアカウント作成
const { account, admin } = await makeTestAccount(source, { tier: 5 });
const { id: authorId1 } = await makeTestUser(source, {
external_id: 'author1',
author_id: 'AUTHOR1',
account_id: account.id,
role: USER_ROLES.AUTHOR,
});
const { id: typistId1 } = await makeTestUser(source, {
external_id: 'typist1',
account_id: account.id,
role: USER_ROLES.TYPIST,
});
const service = module.get<WorkflowsService>(WorkflowsService);
const context = makeContext(admin.external_id);
//実行結果を確認
try {
await service.updateWorkflow(
context,
admin.external_id,
9999,
authorId1,
undefined,
undefined,
[
{
typistId: typistId1,
},
],
);
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST);
expect(e.getResponse()).toEqual(makeErrorResponse('E013002'));
} else {
fail();
}
}
});
it('DBにAuthorが存在しない場合、400エラーとなること', async () => {
const module = await makeTestingModule(source);
// 第五階層のアカウント作成
const { account, admin } = await makeTestAccount(source, { tier: 5 });
const { id: authorId1 } = await makeTestUser(source, {
external_id: 'author1',
author_id: 'AUTHOR1',
account_id: account.id,
role: USER_ROLES.AUTHOR,
});
const { id: typistId1 } = 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 preWorkflow = await createWorkflow(
source,
account.id,
authorId1,
undefined,
undefined,
);
await createWorkflowTypist(source, preWorkflow.id, typistId1);
//作成したデータを確認
{
const workflows = await getWorkflows(source, account.id);
expect(workflows.length).toBe(1);
}
const service = module.get<WorkflowsService>(WorkflowsService);
const context = makeContext(admin.external_id);
//実行結果を確認
try {
await service.updateWorkflow(
context,
admin.external_id,
preWorkflow.id,
9999,
worktypeId,
templateId,
[
{
typistId: typistId1,
},
],
);
} 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: authorId1 } = await makeTestUser(source, {
external_id: 'author1',
author_id: 'AUTHOR1',
account_id: account.id,
role: USER_ROLES.AUTHOR,
});
const { id: typistId1 } = 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 preWorkflow = await createWorkflow(
source,
account.id,
authorId1,
undefined,
undefined,
);
await createWorkflowTypist(source, preWorkflow.id, typistId1);
//作成したデータを確認
{
const workflows = await getWorkflows(source, account.id);
expect(workflows.length).toBe(1);
}
const service = module.get<WorkflowsService>(WorkflowsService);
const context = makeContext(admin.external_id);
//実行結果を確認
try {
await service.updateWorkflow(
context,
admin.external_id,
preWorkflow.id,
authorId1,
9999,
templateId,
[
{
typistId: typistId1,
},
],
);
} 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: authorId1 } = await makeTestUser(source, {
external_id: 'author1',
author_id: 'AUTHOR1',
account_id: account.id,
role: USER_ROLES.AUTHOR,
});
const { id: typistId1 } = await makeTestUser(source, {
external_id: 'typist1',
account_id: account.id,
role: USER_ROLES.TYPIST,
});
const { id: worktypeId } = await createWorktype(
source,
account.id,
'worktype1',
);
const preWorkflow = await createWorkflow(
source,
account.id,
authorId1,
undefined,
undefined,
);
await createWorkflowTypist(source, preWorkflow.id, typistId1);
//作成したデータを確認
{
const workflows = await getWorkflows(source, account.id);
expect(workflows.length).toBe(1);
}
const service = module.get<WorkflowsService>(WorkflowsService);
const context = makeContext(admin.external_id);
//実行結果を確認
try {
await service.updateWorkflow(
context,
admin.external_id,
preWorkflow.id,
authorId1,
worktypeId,
9999,
[
{
typistId: typistId1,
},
],
);
} 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: authorId1 } = await makeTestUser(source, {
external_id: 'author1',
author_id: 'AUTHOR1',
account_id: account.id,
role: USER_ROLES.AUTHOR,
});
const { id: typistId1 } = 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 preWorkflow = await createWorkflow(
source,
account.id,
authorId1,
undefined,
undefined,
);
await createWorkflowTypist(source, preWorkflow.id, typistId1);
//作成したデータを確認
{
const workflows = await getWorkflows(source, account.id);
expect(workflows.length).toBe(1);
}
const service = module.get<WorkflowsService>(WorkflowsService);
const context = makeContext(admin.external_id);
//実行結果を確認
try {
await service.updateWorkflow(
context,
admin.external_id,
preWorkflow.id,
authorId1,
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: authorId1 } = await makeTestUser(source, {
external_id: 'author1',
author_id: 'AUTHOR1',
account_id: account.id,
role: USER_ROLES.AUTHOR,
});
const { id: typistId1 } = 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 preWorkflow = await createWorkflow(
source,
account.id,
authorId1,
undefined,
undefined,
);
await createWorkflowTypist(source, preWorkflow.id, typistId1);
//作成したデータを確認
{
const workflows = await getWorkflows(source, account.id);
expect(workflows.length).toBe(1);
}
const service = module.get<WorkflowsService>(WorkflowsService);
const context = makeContext(admin.external_id);
//実行結果を確認
try {
await service.updateWorkflow(
context,
admin.external_id,
preWorkflow.id,
authorId1,
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: authorId1 } = await makeTestUser(source, {
external_id: 'author1',
author_id: 'AUTHOR1',
account_id: account.id,
role: USER_ROLES.AUTHOR,
});
const { id: typistId1 } = await makeTestUser(source, {
external_id: 'typist1',
account_id: account.id,
role: USER_ROLES.TYPIST,
});
const { id: worktypeId1 } = await createWorktype(
source,
account.id,
'worktype1',
);
await createWorkflow(source, account.id, authorId1, worktypeId1, undefined);
const preWorkflow = await createWorkflow(
source,
account.id,
authorId1,
undefined,
undefined,
);
await createWorkflowTypist(source, preWorkflow.id, typistId1);
//作成したデータを確認
{
const workflows = await getWorkflows(source, account.id);
expect(workflows.length).toBe(2);
}
const service = module.get<WorkflowsService>(WorkflowsService);
const context = makeContext(admin.external_id);
//実行結果を確認
try {
await service.updateWorkflow(
context,
admin.external_id,
preWorkflow.id,
authorId1,
worktypeId1,
undefined,
[
{
typistId: typistId1,
},
],
);
} 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: authorId1 } = await makeTestUser(source, {
external_id: 'author1',
author_id: 'AUTHOR1',
account_id: account.id,
role: USER_ROLES.AUTHOR,
});
const { id: typistId1 } = await makeTestUser(source, {
external_id: 'typist1',
account_id: account.id,
role: USER_ROLES.TYPIST,
});
const preWorkflow = await createWorkflow(
source,
account.id,
authorId1,
undefined,
undefined,
);
await createWorkflowTypist(source, preWorkflow.id, typistId1);
//作成したデータを確認
{
const workflows = await getWorkflows(source, account.id);
const workflowTypists = await getAllWorkflowTypists(source);
expect(workflows.length).toBe(1);
expect(workflows[0].id).toBe(preWorkflow.id);
expect(workflows[0].account_id).toBe(account.id);
expect(workflows[0].author_id).toBe(authorId1);
expect(workflows[0].worktype_id).toBe(null);
expect(workflows[0].template_id).toBe(null);
expect(workflowTypists.length).toBe(1);
}
const service = module.get<WorkflowsService>(WorkflowsService);
const context = makeContext(admin.external_id);
//DBアクセスに失敗するようにする
const workflowsRepositoryService = module.get<WorkflowsRepositoryService>(
WorkflowsRepositoryService,
);
workflowsRepositoryService.updatetWorkflow = jest
.fn()
.mockRejectedValue('DB failed');
//実行結果を確認
try {
await service.updateWorkflow(
context,
admin.external_id,
preWorkflow.id,
authorId1,
undefined,
undefined,
[
{
typistId: typistId1,
},
],
);
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toEqual(HttpStatus.INTERNAL_SERVER_ERROR);
expect(e.getResponse()).toEqual(makeErrorResponse('E009999'));
} else {
fail();
}
}
});
});

View File

@ -1,16 +1,18 @@
import { HttpException, HttpStatus, Injectable, Logger } from '@nestjs/common';
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 { Workflow, WorkflowTypist } from './types/types';
import { AdB2cService } from '../../gateways/adb2c/adb2c.service';
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';
import {
AuthorIdAndWorktypeIdPairAlreadyExistsError,
WorkflowIdNotFoundError,
} from '../../repositories/workflows/errors/types';
@Injectable()
export class WorkflowsService {
@ -196,4 +198,96 @@ export class WorkflowsService {
);
}
}
/**
*
* @param context
* @param externalId
* @param workflowId
* @param authorId
* @param [worktypeId]
* @param [templateId]
* @param [typists]
* @returns workflow
*/
async updateWorkflow(
context: Context,
externalId: string,
workflowId: number,
authorId: number,
worktypeId?: number | undefined,
templateId?: number | undefined,
typists?: WorkflowTypist[],
): Promise<void> {
this.logger.log(
`[IN] [${context.trackingId}] ${this.updateWorkflow.name} | params: { ` +
`externalId: ${externalId}, ` +
`workflowId: ${workflowId}, ` +
`authorId: ${authorId}, ` +
`worktypeId: ${worktypeId}, ` +
`templateId: ${templateId}, ` +
`typists: ${JSON.stringify(typists)} };`,
);
try {
const { account_id: accountId } =
await this.usersRepository.findUserByExternalId(externalId);
await this.workflowsRepository.updatetWorkflow(
accountId,
workflowId,
authorId,
worktypeId,
templateId,
typists,
);
} catch (e) {
this.logger.error(`[${context.trackingId}] error=${e}`);
if (e instanceof Error) {
switch (e.constructor) {
case WorkflowIdNotFoundError:
throw new HttpException(
makeErrorResponse('E013002'),
HttpStatus.BAD_REQUEST,
);
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.updateWorkflow.name}`,
);
}
}
}

View File

@ -1,2 +1,4 @@
// AuthorIDとWorktypeIDのペア重複エラー
export class AuthorIdAndWorktypeIdPairAlreadyExistsError extends Error {}
// WorkflowID存在エラー
export class WorkflowIdNotFoundError extends Error {}

View File

@ -11,7 +11,10 @@ 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';
import {
AuthorIdAndWorktypeIdPairAlreadyExistsError,
WorkflowIdNotFoundError,
} from './errors/types';
@Injectable()
export class WorkflowsRepositoryService {
@ -37,6 +40,9 @@ export class WorkflowsRepositoryService {
typistGroup: true,
},
},
order: {
id: 'ASC',
},
});
return workflows;
@ -158,6 +164,142 @@ export class WorkflowsRepositoryService {
});
}
/**
*
* @param accountId
* @param workflowId
* @param authorId
* @param [worktypeId]
* @param [templateId]
* @param [typists]
* @returns workflow
*/
async updatetWorkflow(
accountId: number,
workflowId: number,
authorId: number,
worktypeId?: number | undefined,
templateId?: number | undefined,
typists?: WorkflowTypist[],
): Promise<void> {
return await this.dataSource.transaction(async (entityManager) => {
const workflowRepo = entityManager.getRepository(Workflow);
// ワークフローの存在確認
const targetWorkflow = await workflowRepo.findOne({
where: { account_id: accountId, id: workflowId },
});
if (!targetWorkflow) {
throw new WorkflowIdNotFoundError(
`workflow not found. id: ${workflowId}`,
);
}
// 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. id: ${templateId}`,
);
}
}
// ルーティング候補ユーザーの存在確認
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 workflowTypistsRepo = entityManager.getRepository(DbWorkflowTypist);
// 既存データの削除
await workflowTypistsRepo.delete({ workflow_id: workflowId });
await workflowRepo.delete(workflowId);
{
// ワークフローの重複確認
const duplicateWorkflow = await workflowRepo.find({
where: {
account_id: accountId,
author_id: authorId,
worktype_id: worktypeId,
},
});
if (duplicateWorkflow.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,
),
);
await workflowTypistsRepo.save(workflowTypists);
});
}
/**
* DBに保存するワークフローデータを作成する
* @param accountId