Merged PR 385: ワークタイプ更新API実装
## 概要 [Task2569: ワークタイプ更新API実装](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/2569) - worktypeID更新APIとテストを実装しました。 ## レビューポイント - リポジトリの更新処理に問題はないか - テストケースは適切か ## UIの変更 - なし ## 動作確認状況 - ローカルで確認
This commit is contained in:
parent
6605658bac
commit
6cba76fa61
@ -54,4 +54,5 @@ export const ErrorCodes = [
|
||||
'E010908', // タイピストグループ不在エラー
|
||||
'E011001', // ワークタイプ重複エラー
|
||||
'E011002', // ワークタイプ登録上限超過エラー
|
||||
'E011003', // ワークタイプ不在エラー
|
||||
] as const;
|
||||
|
||||
@ -43,4 +43,5 @@ export const errors: Errors = {
|
||||
E010908: 'Typist Group not exist Error',
|
||||
E011001: 'Thiw WorkTypeID already used Error',
|
||||
E011002: 'WorkTypeID create limit exceeded Error',
|
||||
E011003: 'WorkTypeID not found Error',
|
||||
};
|
||||
|
||||
@ -759,10 +759,13 @@ export class AccountsController {
|
||||
|
||||
const context = makeContext(userId);
|
||||
|
||||
console.log('worktypeId: ', worktypeId);
|
||||
console.log('description: ', description);
|
||||
console.log('id: ', id);
|
||||
console.log(context.trackingId);
|
||||
await this.accountService.updateWorktype(
|
||||
context,
|
||||
userId,
|
||||
id,
|
||||
worktypeId,
|
||||
description,
|
||||
);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
@ -61,6 +61,7 @@ import {
|
||||
selectOrderLicense,
|
||||
} from '../licenses/test/utility';
|
||||
import { WorktypesRepositoryService } from '../../repositories/worktypes/worktypes.repository.service';
|
||||
import { Worktype } from '../../repositories/worktypes/entity/worktype.entity';
|
||||
|
||||
describe('createAccount', () => {
|
||||
let source: DataSource = null;
|
||||
@ -3591,6 +3592,275 @@ describe('createWorktype', () => {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('updateWorktype', () => {
|
||||
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('Worktypeを更新できる', async () => {
|
||||
const module = await makeTestingModule(source);
|
||||
// 第五階層のアカウント作成
|
||||
const { account, admin } = await makeTestAccount(source, { tier: 5 });
|
||||
|
||||
const service = module.get<AccountsService>(AccountsService);
|
||||
const context = makeContext(admin.external_id);
|
||||
|
||||
const worktype = new Worktype();
|
||||
worktype.custom_worktype_id = 'worktypeID1';
|
||||
worktype.description = 'description1';
|
||||
|
||||
await createWorktype(
|
||||
source,
|
||||
account.id,
|
||||
worktype.custom_worktype_id,
|
||||
worktype.description,
|
||||
);
|
||||
|
||||
// Worktypeを確認
|
||||
const worktypes = await getWorktypes(source, account.id);
|
||||
{
|
||||
expect(worktypes.length).toBe(1);
|
||||
expect(worktypes[0].custom_worktype_id).toBe(worktype.custom_worktype_id);
|
||||
expect(worktypes[0].description).toBe(worktype.description);
|
||||
}
|
||||
|
||||
const updateWorktypeId = 'updateWorktypeID';
|
||||
const updateDescription = 'updateDescription';
|
||||
|
||||
await service.updateWorktype(
|
||||
context,
|
||||
admin.external_id,
|
||||
worktypes[0].id,
|
||||
updateWorktypeId,
|
||||
updateDescription,
|
||||
);
|
||||
|
||||
//実行結果を確認
|
||||
{
|
||||
const worktypes = await getWorktypes(source, account.id);
|
||||
expect(worktypes.length).toBe(1);
|
||||
expect(worktypes[0].custom_worktype_id).toBe(updateWorktypeId);
|
||||
expect(worktypes[0].description).toBe(updateDescription);
|
||||
}
|
||||
});
|
||||
|
||||
it('指定したIDが登録されていない場合、400エラーとなること', async () => {
|
||||
const module = await makeTestingModule(source);
|
||||
// 第五階層のアカウント作成
|
||||
const { account, admin } = await makeTestAccount(source, { tier: 5 });
|
||||
|
||||
const service = module.get<AccountsService>(AccountsService);
|
||||
const context = makeContext(admin.external_id);
|
||||
|
||||
const worktype = new Worktype();
|
||||
worktype.custom_worktype_id = 'worktypeID1';
|
||||
worktype.description = 'description1';
|
||||
|
||||
await createWorktype(
|
||||
source,
|
||||
account.id,
|
||||
worktype.custom_worktype_id,
|
||||
worktype.description,
|
||||
);
|
||||
|
||||
// Worktypeを確認
|
||||
{
|
||||
const worktypes = await getWorktypes(source, account.id);
|
||||
expect(worktypes.length).toBe(1);
|
||||
expect(worktypes[0].custom_worktype_id).toBe(worktype.custom_worktype_id);
|
||||
expect(worktypes[0].description).toBe(worktype.description);
|
||||
}
|
||||
|
||||
try {
|
||||
await service.updateWorktype(
|
||||
context,
|
||||
admin.external_id,
|
||||
999,
|
||||
'newWorktypeID',
|
||||
'newDescription',
|
||||
);
|
||||
} catch (e) {
|
||||
if (e instanceof HttpException) {
|
||||
expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST);
|
||||
expect(e.getResponse()).toEqual(makeErrorResponse('E011003'));
|
||||
} else {
|
||||
fail();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it('WorktypeIDが登録済みのWorktypeIDと重複した場合、400エラーとなること', async () => {
|
||||
const module = await makeTestingModule(source);
|
||||
// 第五階層のアカウント作成
|
||||
const { account, admin } = await makeTestAccount(source, { tier: 5 });
|
||||
|
||||
const service = module.get<AccountsService>(AccountsService);
|
||||
const context = makeContext(admin.external_id);
|
||||
const worktype1 = new Worktype();
|
||||
worktype1.custom_worktype_id = 'worktypeID1';
|
||||
worktype1.description = 'description1';
|
||||
|
||||
const worktype2 = new Worktype();
|
||||
worktype2.custom_worktype_id = 'worktypeID2';
|
||||
worktype2.description = 'description2';
|
||||
|
||||
await createWorktype(
|
||||
source,
|
||||
account.id,
|
||||
worktype1.custom_worktype_id,
|
||||
worktype1.description,
|
||||
);
|
||||
await createWorktype(
|
||||
source,
|
||||
account.id,
|
||||
worktype2.custom_worktype_id,
|
||||
worktype2.description,
|
||||
);
|
||||
|
||||
//作成したデータを確認
|
||||
const worktypes = await getWorktypes(source, account.id);
|
||||
{
|
||||
expect(worktypes.length).toBe(2);
|
||||
expect(worktypes[0].custom_worktype_id).toBe(
|
||||
worktype1.custom_worktype_id,
|
||||
);
|
||||
expect(worktypes[0].description).toBe(worktype1.description);
|
||||
expect(worktypes[1].custom_worktype_id).toBe(
|
||||
worktype2.custom_worktype_id,
|
||||
);
|
||||
expect(worktypes[1].description).toBe(worktype2.description);
|
||||
}
|
||||
|
||||
try {
|
||||
await service.updateWorktype(
|
||||
context,
|
||||
admin.external_id,
|
||||
worktypes[0].id,
|
||||
worktype2.custom_worktype_id,
|
||||
worktype2.description,
|
||||
);
|
||||
} catch (e) {
|
||||
if (e instanceof HttpException) {
|
||||
expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST);
|
||||
expect(e.getResponse()).toEqual(makeErrorResponse('E011001'));
|
||||
} else {
|
||||
fail();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it('WorktypeIDが登録済みの指定IDのWorktypeIDと重複した場合でも更新できること', async () => {
|
||||
const module = await makeTestingModule(source);
|
||||
// 第五階層のアカウント作成
|
||||
const { account, admin } = await makeTestAccount(source, { tier: 5 });
|
||||
|
||||
const service = module.get<AccountsService>(AccountsService);
|
||||
const context = makeContext(admin.external_id);
|
||||
|
||||
const worktype = new Worktype();
|
||||
worktype.custom_worktype_id = 'worktypeID1';
|
||||
worktype.description = 'description1';
|
||||
|
||||
await createWorktype(
|
||||
source,
|
||||
account.id,
|
||||
worktype.custom_worktype_id,
|
||||
worktype.description,
|
||||
);
|
||||
|
||||
// Worktypeを確認
|
||||
const worktypes = await getWorktypes(source, account.id);
|
||||
{
|
||||
expect(worktypes.length).toBe(1);
|
||||
expect(worktypes[0].custom_worktype_id).toBe(worktype.custom_worktype_id);
|
||||
expect(worktypes[0].description).toBe(worktype.description);
|
||||
}
|
||||
|
||||
const updateDescription = 'updateDescription';
|
||||
|
||||
await service.updateWorktype(
|
||||
context,
|
||||
admin.external_id,
|
||||
worktypes[0].id,
|
||||
worktype.custom_worktype_id,
|
||||
updateDescription,
|
||||
);
|
||||
|
||||
//実行結果を確認
|
||||
{
|
||||
const worktypes = await getWorktypes(source, account.id);
|
||||
expect(worktypes.length).toBe(1);
|
||||
expect(worktypes[0].custom_worktype_id).toBe(worktype.custom_worktype_id);
|
||||
expect(worktypes[0].description).toBe(updateDescription);
|
||||
}
|
||||
});
|
||||
|
||||
it('DBアクセスに失敗した場合、500エラーを返却する', async () => {
|
||||
const module = await makeTestingModule(source);
|
||||
// 第五階層のアカウント作成
|
||||
const { account, admin } = await makeTestAccount(source, { tier: 5 });
|
||||
|
||||
const service = module.get<AccountsService>(AccountsService);
|
||||
const context = makeContext(admin.external_id);
|
||||
|
||||
const worktype = new Worktype();
|
||||
worktype.custom_worktype_id = 'worktypeID1';
|
||||
worktype.description = 'description1';
|
||||
|
||||
await createWorktype(
|
||||
source,
|
||||
account.id,
|
||||
worktype.custom_worktype_id,
|
||||
worktype.description,
|
||||
);
|
||||
|
||||
// Worktypeを確認
|
||||
const worktypes = await getWorktypes(source, account.id);
|
||||
{
|
||||
expect(worktypes.length).toBe(1);
|
||||
expect(worktypes[0].custom_worktype_id).toBe(worktype.custom_worktype_id);
|
||||
expect(worktypes[0].description).toBe(worktype.description);
|
||||
}
|
||||
|
||||
//DBアクセスに失敗するようにする
|
||||
const worktypeService = module.get<WorktypesRepositoryService>(
|
||||
WorktypesRepositoryService,
|
||||
);
|
||||
worktypeService.updateWorktype = jest.fn().mockRejectedValue('DB failed');
|
||||
|
||||
try {
|
||||
await service.updateWorktype(
|
||||
context,
|
||||
admin.external_id,
|
||||
worktypes[0].id,
|
||||
'newWorktype',
|
||||
'newDescription',
|
||||
);
|
||||
} catch (e) {
|
||||
if (e instanceof HttpException) {
|
||||
expect(e.getStatus()).toEqual(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
expect(e.getResponse()).toEqual(makeErrorResponse('E009999'));
|
||||
} else {
|
||||
fail();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('ライセンス発行キャンセル', () => {
|
||||
let source: DataSource = null;
|
||||
beforeEach(async () => {
|
||||
|
||||
@ -53,6 +53,7 @@ import { WorktypesRepositoryService } from '../../repositories/worktypes/worktyp
|
||||
import {
|
||||
WorktypeIdAlreadyExistsError,
|
||||
WorktypeIdMaxCountError,
|
||||
WorktypeIdNotFoundError,
|
||||
} from '../../repositories/worktypes/errors/types';
|
||||
|
||||
@Injectable()
|
||||
@ -1241,4 +1242,74 @@ export class AccountsService {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ワークタイプを更新します
|
||||
* @param context
|
||||
* @param externalId
|
||||
* @param id ワークタイプの内部ID
|
||||
* @param worktypeId ユーザーが設定するワークタイプ名
|
||||
* @param [description]
|
||||
* @returns worktype
|
||||
*/
|
||||
async updateWorktype(
|
||||
context: Context,
|
||||
externalId: string,
|
||||
id: number,
|
||||
worktypeId: string,
|
||||
description?: string,
|
||||
): Promise<void> {
|
||||
this.logger.log(
|
||||
`[IN] [${context.trackingId}] ${this.updateWorktype.name} | params: { ` +
|
||||
`externalId: ${externalId}, ` +
|
||||
`id: ${id}, ` +
|
||||
`worktypeId: ${worktypeId}, ` +
|
||||
`description: ${description} };`,
|
||||
);
|
||||
|
||||
try {
|
||||
// 外部IDをもとにユーザー情報を取得する
|
||||
const { account_id: accountId } =
|
||||
await this.usersRepository.findUserByExternalId(externalId);
|
||||
|
||||
// ワークタイプを更新する
|
||||
await this.worktypesRepository.updateWorktype(
|
||||
accountId,
|
||||
id,
|
||||
worktypeId,
|
||||
description,
|
||||
);
|
||||
} catch (e) {
|
||||
this.logger.error(`error=${e}`);
|
||||
if (e instanceof Error) {
|
||||
switch (e.constructor) {
|
||||
// ユーザーが設定したWorktypeIDが既存WorktypeのWorktypeIDと重複する場合は400エラーを返す
|
||||
case WorktypeIdAlreadyExistsError:
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E011001'),
|
||||
HttpStatus.BAD_REQUEST,
|
||||
);
|
||||
// 内部IDで指定されたWorktypeが存在しない場合は400エラーを返す
|
||||
case WorktypeIdNotFoundError:
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E011003'),
|
||||
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.updateWorktype.name}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,3 +2,5 @@
|
||||
export class WorktypeIdAlreadyExistsError extends Error {}
|
||||
// WorktypeID登録上限エラー
|
||||
export class WorktypeIdMaxCountError extends Error {}
|
||||
// WorktypeID不在エラー
|
||||
export class WorktypeIdNotFoundError extends Error {}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { DataSource } from 'typeorm';
|
||||
import { DataSource, Not } from 'typeorm';
|
||||
import { Worktype } from './entity/worktype.entity';
|
||||
import {
|
||||
OPTION_ITEM_NUM,
|
||||
@ -9,6 +9,7 @@ import {
|
||||
import {
|
||||
WorktypeIdAlreadyExistsError,
|
||||
WorktypeIdMaxCountError,
|
||||
WorktypeIdNotFoundError,
|
||||
} from './errors/types';
|
||||
import { OptionItem } from '../option_items/entity/option_item.entity';
|
||||
|
||||
@ -34,14 +35,13 @@ export class WorktypesRepositoryService {
|
||||
* @param accountId
|
||||
* @param worktypeId
|
||||
* @param [description]
|
||||
* @returns worktype
|
||||
*/
|
||||
async createWorktype(
|
||||
accountId: number,
|
||||
worktypeId: string,
|
||||
description?: string,
|
||||
): Promise<Worktype> {
|
||||
return await this.dataSource.transaction(async (entityManager) => {
|
||||
): Promise<void> {
|
||||
await this.dataSource.transaction(async (entityManager) => {
|
||||
const worktypeRepo = entityManager.getRepository(Worktype);
|
||||
const optionItemRepo = entityManager.getRepository(OptionItem);
|
||||
|
||||
@ -86,8 +86,53 @@ export class WorktypesRepositoryService {
|
||||
});
|
||||
|
||||
await optionItemRepo.save(newOptionItems);
|
||||
});
|
||||
}
|
||||
|
||||
return worktype;
|
||||
/**
|
||||
* ワークタイプを更新する
|
||||
* @param accountId
|
||||
* @param id ワークタイプの内部ID
|
||||
* @param worktypeId ユーザーが設定するワークタイプ名
|
||||
* @param [description]
|
||||
*/
|
||||
async updateWorktype(
|
||||
accountId: number,
|
||||
id: number,
|
||||
worktypeId: string,
|
||||
description?: string,
|
||||
): Promise<void> {
|
||||
await this.dataSource.transaction(async (entityManager) => {
|
||||
const worktypeRepo = entityManager.getRepository(Worktype);
|
||||
|
||||
const worktype = await worktypeRepo.findOne({
|
||||
where: { account_id: accountId, id: id },
|
||||
});
|
||||
|
||||
// ワークタイプが存在しない場合はエラー
|
||||
if (!worktype) {
|
||||
throw new WorktypeIdNotFoundError(`Worktype is not found. id: ${id}`);
|
||||
}
|
||||
|
||||
const duplicatedWorktype = await worktypeRepo.findOne({
|
||||
where: {
|
||||
account_id: accountId,
|
||||
custom_worktype_id: worktypeId,
|
||||
id: Not(id),
|
||||
},
|
||||
});
|
||||
|
||||
// ワークタイプIDが重複している場合はエラー
|
||||
if (duplicatedWorktype) {
|
||||
throw new WorktypeIdAlreadyExistsError(
|
||||
`WorktypeID is already exists. WorktypeID: ${worktypeId}`,
|
||||
);
|
||||
}
|
||||
|
||||
// ワークタイプを更新
|
||||
worktype.custom_worktype_id = worktypeId;
|
||||
worktype.description = description;
|
||||
await worktypeRepo.save(worktype);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user