Merged PR 371: API実装

## 概要
[Task2505: API実装](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/2505)

- ワークタイプ一覧取得APIとテストを実装しました。
  - ワークタイプテーブルのリポジトリも実装しています。

## レビューポイント
- リポジトリの実装に問題はないか
- テスト実装に不足はないか

## UIの変更
- なし

## 動作確認状況
- ローカルで確認
This commit is contained in:
makabe.t 2023-09-01 00:24:01 +00:00
parent bb0bdce84c
commit 2da40e278b
14 changed files with 344 additions and 27 deletions

View File

@ -759,7 +759,7 @@
"content": { "content": {
"application/json": { "application/json": {
"schema": { "schema": {
"$ref": "#/components/schemas/GetWorkTypesResponse" "$ref": "#/components/schemas/GetWorktypesResponse"
} }
} }
} }
@ -2735,24 +2735,24 @@
"required": ["orderedAccountId", "poNumber"] "required": ["orderedAccountId", "poNumber"]
}, },
"CancelIssueResponse": { "type": "object", "properties": {} }, "CancelIssueResponse": { "type": "object", "properties": {} },
"WorkType": { "Worktype": {
"type": "object", "type": "object",
"properties": { "properties": {
"id": { "type": "number", "description": "WorkTypeのID" }, "id": { "type": "number", "description": "WorktypeのID" },
"workTypeId": { "type": "string", "description": "WorkTypeID" }, "worktypeId": { "type": "string", "description": "WorktypeID" },
"description": { "type": "string", "description": "WorkTypeの説明" } "description": { "type": "string", "description": "Worktypeの説明" }
}, },
"required": ["id", "workTypeId"] "required": ["id", "worktypeId"]
}, },
"GetWorkTypesResponse": { "GetWorktypesResponse": {
"type": "object", "type": "object",
"properties": { "properties": {
"workTypes": { "worktypes": {
"type": "array", "type": "array",
"items": { "$ref": "#/components/schemas/WorkType" } "items": { "$ref": "#/components/schemas/Worktype" }
} }
}, },
"required": ["workTypes"] "required": ["worktypes"]
}, },
"CreateWorktypesRequest": { "CreateWorktypesRequest": {
"type": "object", "type": "object",

View File

@ -40,6 +40,7 @@ import { CheckoutPermissionsRepositoryModule } from './repositories/checkout_per
import { UserGroupsRepositoryModule } from './repositories/user_groups/user_groups.repository.module'; import { UserGroupsRepositoryModule } from './repositories/user_groups/user_groups.repository.module';
import { SortCriteriaRepositoryModule } from './repositories/sort_criteria/sort_criteria.repository.module'; import { SortCriteriaRepositoryModule } from './repositories/sort_criteria/sort_criteria.repository.module';
import { TemplateFilesRepositoryModule } from './repositories/template_files/template_files.repository.module'; import { TemplateFilesRepositoryModule } from './repositories/template_files/template_files.repository.module';
import { WorktypesRepositoryModule } from './repositories/worktypes/worktypes.repository.module';
@Module({ @Module({
imports: [ imports: [
@ -94,6 +95,7 @@ import { TemplateFilesRepositoryModule } from './repositories/template_files/tem
BlobstorageModule, BlobstorageModule,
AuthGuardsModule, AuthGuardsModule,
SortCriteriaRepositoryModule, SortCriteriaRepositoryModule,
WorktypesRepositoryModule,
], ],
controllers: [ controllers: [
HealthController, HealthController,

View File

@ -17,6 +17,7 @@ import { LicensesRepositoryModule } from '../../repositories/licenses/licenses.r
import { AudioFilesRepositoryModule } from '../../repositories/audio_files/audio_files.repository.module'; import { AudioFilesRepositoryModule } from '../../repositories/audio_files/audio_files.repository.module';
import { AudioOptionItemsRepositoryModule } from '../../repositories/audio_option_items/audio_option_items.repository.module'; import { AudioOptionItemsRepositoryModule } from '../../repositories/audio_option_items/audio_option_items.repository.module';
import { CheckoutPermissionsRepositoryModule } from '../../repositories/checkout_permissions/checkout_permissions.repository.module'; import { CheckoutPermissionsRepositoryModule } from '../../repositories/checkout_permissions/checkout_permissions.repository.module';
import { WorktypesRepositoryModule } from '../../repositories/worktypes/worktypes.repository.module';
import { NotificationModule } from '../../features//notification/notification.module'; import { NotificationModule } from '../../features//notification/notification.module';
import { NotificationhubModule } from '../../gateways/notificationhub/notificationhub.module'; import { NotificationhubModule } from '../../gateways/notificationhub/notificationhub.module';
import { BlobstorageModule } from '../../gateways/blobstorage/blobstorage.module'; import { BlobstorageModule } from '../../gateways/blobstorage/blobstorage.module';
@ -63,6 +64,7 @@ export const makeTestingModule = async (
BlobstorageModule, BlobstorageModule,
AuthGuardsModule, AuthGuardsModule,
SortCriteriaRepositoryModule, SortCriteriaRepositoryModule,
WorktypesRepositoryModule,
], ],
providers: [ providers: [
AuthService, AuthService,

View File

@ -42,7 +42,7 @@ import {
UpdateTypistGroupRequestParam, UpdateTypistGroupRequestParam,
CancelIssueRequest, CancelIssueRequest,
CancelIssueResponse, CancelIssueResponse,
GetWorkTypesResponse, GetWorktypesResponse,
CreateWorktypeResponse, CreateWorktypeResponse,
CreateWorktypesRequest, CreateWorktypesRequest,
} from './types/types'; } from './types/types';
@ -645,7 +645,7 @@ export class AccountsController {
@Get('/worktypes') @Get('/worktypes')
@ApiResponse({ @ApiResponse({
status: HttpStatus.OK, status: HttpStatus.OK,
type: GetWorkTypesResponse, type: GetWorktypesResponse,
description: '成功時のレスポンス', description: '成功時のレスポンス',
}) })
@ApiResponse({ @ApiResponse({
@ -662,18 +662,14 @@ export class AccountsController {
@ApiBearerAuth() @ApiBearerAuth()
@UseGuards(AuthGuard) @UseGuards(AuthGuard)
@UseGuards(RoleGuard.requireds({ roles: [ADMIN_ROLES.ADMIN] })) @UseGuards(RoleGuard.requireds({ roles: [ADMIN_ROLES.ADMIN] }))
async getWorktypes(@Req() req: Request): Promise<GetWorkTypesResponse> { async getWorktypes(@Req() req: Request): Promise<GetWorktypesResponse> {
const token = retrieveAuthorizationToken(req); const token = retrieveAuthorizationToken(req);
const { userId } = jwt.decode(token, { json: true }) as AccessToken; const { userId } = jwt.decode(token, { json: true }) as AccessToken;
const context = makeContext(userId); const context = makeContext(userId);
console.log(context.trackingId); const worktypes = await this.accountService.getWorktypes(context, userId);
return { return worktypes;
workTypes: [
{ id: 1, workTypeId: 'workTypeId', description: 'description' },
],
};
} }
@Post('/worktypes') @Post('/worktypes')

View File

@ -8,6 +8,7 @@ import { AccountsService } from './accounts.service';
import { AdB2cModule } from '../../gateways/adb2c/adb2c.module'; import { AdB2cModule } from '../../gateways/adb2c/adb2c.module';
import { UserGroupsRepositoryModule } from '../../repositories/user_groups/user_groups.repository.module'; import { UserGroupsRepositoryModule } from '../../repositories/user_groups/user_groups.repository.module';
import { BlobstorageModule } from '../../gateways/blobstorage/blobstorage.module'; import { BlobstorageModule } from '../../gateways/blobstorage/blobstorage.module';
import { WorktypesRepositoryModule } from '../../repositories/worktypes/worktypes.repository.module';
@Module({ @Module({
imports: [ imports: [
@ -15,6 +16,7 @@ import { BlobstorageModule } from '../../gateways/blobstorage/blobstorage.module
UsersRepositoryModule, UsersRepositoryModule,
LicensesRepositoryModule, LicensesRepositoryModule,
UserGroupsRepositoryModule, UserGroupsRepositoryModule,
WorktypesRepositoryModule,
SendGridModule, SendGridModule,
AdB2cModule, AdB2cModule,
BlobstorageModule, BlobstorageModule,

View File

@ -9,15 +9,18 @@ import {
makeDefaultSendGridlValue, makeDefaultSendGridlValue,
makeDefaultUserGroupsRepositoryMockValue, makeDefaultUserGroupsRepositoryMockValue,
makeDefaultUsersRepositoryMockValue, makeDefaultUsersRepositoryMockValue,
makeDefaultWorktypesRepositoryMockValue,
} from './test/accounts.service.mock'; } from './test/accounts.service.mock';
import { makeDefaultConfigValue } from '../users/test/users.service.mock'; import { makeDefaultConfigValue } from '../users/test/users.service.mock';
import { import {
createLicense, createLicense,
createLicenseOrder, createLicenseOrder,
createLicenseSetExpiryDateAndStatus, createLicenseSetExpiryDateAndStatus,
createWorktype,
getSortCriteria, getSortCriteria,
getTypistGroup, getTypistGroup,
getTypistGroupMember, getTypistGroupMember,
getWorktypes,
} from './test/utility'; } from './test/utility';
import { DataSource } from 'typeorm'; import { DataSource } from 'typeorm';
import { makeTestingModule } from '../../common/test/modules'; import { makeTestingModule } from '../../common/test/modules';
@ -42,6 +45,7 @@ import {
import { AdB2cService } from '../../gateways/adb2c/adb2c.service'; import { AdB2cService } from '../../gateways/adb2c/adb2c.service';
import { BlobstorageService } from '../../gateways/blobstorage/blobstorage.service'; import { BlobstorageService } from '../../gateways/blobstorage/blobstorage.service';
import { UserGroupsRepositoryService } from '../../repositories/user_groups/user_groups.repository.service'; import { UserGroupsRepositoryService } from '../../repositories/user_groups/user_groups.repository.service';
import { WorktypesRepositoryService } from '../../repositories/worktypes/worktypes.repository.service';
describe('createAccount', () => { describe('createAccount', () => {
let source: DataSource = null; let source: DataSource = null;
@ -1481,6 +1485,8 @@ describe('AccountsService', () => {
const blobStorageMockValue = makeBlobStorageServiceMockValue(); const blobStorageMockValue = makeBlobStorageServiceMockValue();
const licensesRepositoryMockValue = const licensesRepositoryMockValue =
makeDefaultLicensesRepositoryMockValue(); makeDefaultLicensesRepositoryMockValue();
const worktypesRepositoryMockValue =
makeDefaultWorktypesRepositoryMockValue();
const service = await makeAccountsServiceMock( const service = await makeAccountsServiceMock(
accountsRepositoryMockValue, accountsRepositoryMockValue,
usersRepositoryMockValue, usersRepositoryMockValue,
@ -1490,6 +1496,7 @@ describe('AccountsService', () => {
sendGridMockValue, sendGridMockValue,
blobStorageMockValue, blobStorageMockValue,
licensesRepositoryMockValue, licensesRepositoryMockValue,
worktypesRepositoryMockValue,
); );
expect(await service.getLicenseSummary(accountId)).toEqual( expect(await service.getLicenseSummary(accountId)).toEqual(
expectedAccountLisenceCounts, expectedAccountLisenceCounts,
@ -1510,6 +1517,8 @@ describe('AccountsService', () => {
const blobStorageMockValue = makeBlobStorageServiceMockValue(); const blobStorageMockValue = makeBlobStorageServiceMockValue();
const licensesRepositoryMockValue = const licensesRepositoryMockValue =
makeDefaultLicensesRepositoryMockValue(); makeDefaultLicensesRepositoryMockValue();
const worktypesRepositoryMockValue =
makeDefaultWorktypesRepositoryMockValue();
const service = await makeAccountsServiceMock( const service = await makeAccountsServiceMock(
accountsRepositoryMockValue, accountsRepositoryMockValue,
usersRepositoryMockValue, usersRepositoryMockValue,
@ -1519,6 +1528,7 @@ describe('AccountsService', () => {
sendGridMockValue, sendGridMockValue,
blobStorageMockValue, blobStorageMockValue,
licensesRepositoryMockValue, licensesRepositoryMockValue,
worktypesRepositoryMockValue,
); );
await expect(service.getLicenseSummary(accountId)).rejects.toEqual( await expect(service.getLicenseSummary(accountId)).rejects.toEqual(
new HttpException( new HttpException(
@ -1541,6 +1551,8 @@ describe('AccountsService', () => {
const blobStorageMockValue = makeBlobStorageServiceMockValue(); const blobStorageMockValue = makeBlobStorageServiceMockValue();
const licensesRepositoryMockValue = const licensesRepositoryMockValue =
makeDefaultLicensesRepositoryMockValue(); makeDefaultLicensesRepositoryMockValue();
const worktypesRepositoryMockValue =
makeDefaultWorktypesRepositoryMockValue();
const service = await makeAccountsServiceMock( const service = await makeAccountsServiceMock(
accountsRepositoryMockValue, accountsRepositoryMockValue,
usersRepositoryMockValue, usersRepositoryMockValue,
@ -1550,6 +1562,7 @@ describe('AccountsService', () => {
sendGridMockValue, sendGridMockValue,
blobStorageMockValue, blobStorageMockValue,
licensesRepositoryMockValue, licensesRepositoryMockValue,
worktypesRepositoryMockValue,
); );
expect(await service.getTypists(externalId)).toEqual([ expect(await service.getTypists(externalId)).toEqual([
{ id: 1, name: 'Typist1' }, { id: 1, name: 'Typist1' },
@ -1571,6 +1584,8 @@ describe('AccountsService', () => {
const blobStorageMockValue = makeBlobStorageServiceMockValue(); const blobStorageMockValue = makeBlobStorageServiceMockValue();
const licensesRepositoryMockValue = const licensesRepositoryMockValue =
makeDefaultLicensesRepositoryMockValue(); makeDefaultLicensesRepositoryMockValue();
const worktypesRepositoryMockValue =
makeDefaultWorktypesRepositoryMockValue();
const service = await makeAccountsServiceMock( const service = await makeAccountsServiceMock(
accountsRepositoryMockValue, accountsRepositoryMockValue,
usersRepositoryMockValue, usersRepositoryMockValue,
@ -1580,6 +1595,7 @@ describe('AccountsService', () => {
sendGridMockValue, sendGridMockValue,
blobStorageMockValue, blobStorageMockValue,
licensesRepositoryMockValue, licensesRepositoryMockValue,
worktypesRepositoryMockValue,
); );
await expect(service.getTypists(externalId)).rejects.toEqual( await expect(service.getTypists(externalId)).rejects.toEqual(
new HttpException( new HttpException(
@ -1602,6 +1618,8 @@ describe('AccountsService', () => {
const blobStorageMockValue = makeBlobStorageServiceMockValue(); const blobStorageMockValue = makeBlobStorageServiceMockValue();
const licensesRepositoryMockValue = const licensesRepositoryMockValue =
makeDefaultLicensesRepositoryMockValue(); makeDefaultLicensesRepositoryMockValue();
const worktypesRepositoryMockValue =
makeDefaultWorktypesRepositoryMockValue();
const service = await makeAccountsServiceMock( const service = await makeAccountsServiceMock(
accountsRepositoryMockValue, accountsRepositoryMockValue,
usersRepositoryMockValue, usersRepositoryMockValue,
@ -1611,6 +1629,7 @@ describe('AccountsService', () => {
sendGridMockValue, sendGridMockValue,
blobStorageMockValue, blobStorageMockValue,
licensesRepositoryMockValue, licensesRepositoryMockValue,
worktypesRepositoryMockValue,
); );
await expect(service.getTypists(externalId)).rejects.toEqual( await expect(service.getTypists(externalId)).rejects.toEqual(
new HttpException( new HttpException(
@ -1633,6 +1652,8 @@ describe('AccountsService', () => {
const blobStorageMockValue = makeBlobStorageServiceMockValue(); const blobStorageMockValue = makeBlobStorageServiceMockValue();
const licensesRepositoryMockValue = const licensesRepositoryMockValue =
makeDefaultLicensesRepositoryMockValue(); makeDefaultLicensesRepositoryMockValue();
const worktypesRepositoryMockValue =
makeDefaultWorktypesRepositoryMockValue();
const service = await makeAccountsServiceMock( const service = await makeAccountsServiceMock(
accountsRepositoryMockValue, accountsRepositoryMockValue,
usersRepositoryMockValue, usersRepositoryMockValue,
@ -1642,6 +1663,7 @@ describe('AccountsService', () => {
sendGridMockValue, sendGridMockValue,
blobStorageMockValue, blobStorageMockValue,
licensesRepositoryMockValue, licensesRepositoryMockValue,
worktypesRepositoryMockValue,
); );
expect(await service.getTypistGroups(externalId)).toEqual([ expect(await service.getTypistGroups(externalId)).toEqual([
@ -1663,6 +1685,8 @@ describe('AccountsService', () => {
const blobStorageMockValue = makeBlobStorageServiceMockValue(); const blobStorageMockValue = makeBlobStorageServiceMockValue();
const licensesRepositoryMockValue = const licensesRepositoryMockValue =
makeDefaultLicensesRepositoryMockValue(); makeDefaultLicensesRepositoryMockValue();
const worktypesRepositoryMockValue =
makeDefaultWorktypesRepositoryMockValue();
const service = await makeAccountsServiceMock( const service = await makeAccountsServiceMock(
accountsRepositoryMockValue, accountsRepositoryMockValue,
usersRepositoryMockValue, usersRepositoryMockValue,
@ -1672,6 +1696,7 @@ describe('AccountsService', () => {
sendGridMockValue, sendGridMockValue,
blobStorageMockValue, blobStorageMockValue,
licensesRepositoryMockValue, licensesRepositoryMockValue,
worktypesRepositoryMockValue,
); );
await expect(service.getTypistGroups(externalId)).rejects.toEqual( await expect(service.getTypistGroups(externalId)).rejects.toEqual(
@ -1695,6 +1720,8 @@ describe('AccountsService', () => {
const blobStorageMockValue = makeBlobStorageServiceMockValue(); const blobStorageMockValue = makeBlobStorageServiceMockValue();
const licensesRepositoryMockValue = const licensesRepositoryMockValue =
makeDefaultLicensesRepositoryMockValue(); makeDefaultLicensesRepositoryMockValue();
const worktypesRepositoryMockValue =
makeDefaultWorktypesRepositoryMockValue();
const service = await makeAccountsServiceMock( const service = await makeAccountsServiceMock(
accountsRepositoryMockValue, accountsRepositoryMockValue,
usersRepositoryMockValue, usersRepositoryMockValue,
@ -1704,6 +1731,7 @@ describe('AccountsService', () => {
sendGridMockValue, sendGridMockValue,
blobStorageMockValue, blobStorageMockValue,
licensesRepositoryMockValue, licensesRepositoryMockValue,
worktypesRepositoryMockValue,
); );
await expect(service.getTypistGroups(externalId)).rejects.toEqual( await expect(service.getTypistGroups(externalId)).rejects.toEqual(
@ -2053,6 +2081,8 @@ describe('getOrderHistories', () => {
const limit = 0; const limit = 0;
const offset = 0; const offset = 0;
const accountId = 0; const accountId = 0;
const worktypesRepositoryMockValue =
makeDefaultWorktypesRepositoryMockValue();
const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue(); const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue();
usersRepositoryMockValue.findTypistUsers = new Error(); usersRepositoryMockValue.findTypistUsers = new Error();
const userGroupsRepositoryMockValue = const userGroupsRepositoryMockValue =
@ -2077,6 +2107,7 @@ describe('getOrderHistories', () => {
sendGridMockValue, sendGridMockValue,
blobStorageMockValue, blobStorageMockValue,
licensesRepositoryMockValue, licensesRepositoryMockValue,
worktypesRepositoryMockValue,
); );
await expect( await expect(
service.getOrderHistories(limit, offset, accountId), service.getOrderHistories(limit, offset, accountId),
@ -3125,3 +3156,110 @@ describe('updateTypistGroup', () => {
} }
}); });
}); });
describe('getWorktypes', () => {
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);
await createWorktype(source, account.id, 'worktype1', 'description1');
await createWorktype(source, account.id, 'worktype2');
//作成したデータを確認
const worktypes = await getWorktypes(source, account.id);
{
expect(worktypes.length).toBe(2);
expect(worktypes[0].custom_worktype_id).toBe('worktype1');
expect(worktypes[1].custom_worktype_id).toBe('worktype2');
expect(worktypes[0].description).toBe('description1');
expect(worktypes[1].description).toBeNull();
}
const resWorktypes = await service.getWorktypes(context, admin.external_id);
//実行結果を確認
{
expect(resWorktypes.worktypes.length).toBe(2);
expect(resWorktypes.worktypes[0].worktypeId).toBe('worktype1');
expect(resWorktypes.worktypes[1].worktypeId).toBe('worktype2');
expect(resWorktypes.worktypes[0].description).toBe('description1');
expect(resWorktypes.worktypes[1].description).toBe(undefined);
}
});
it('アカウント内のWorktypeを取得できる0件', async () => {
const module = await makeTestingModule(source);
// 第五階層のアカウント作成
const { admin } = await makeTestAccount(source, { tier: 5 });
const service = module.get<AccountsService>(AccountsService);
const context = makeContext(admin.external_id);
const resWorktypes = await service.getWorktypes(context, admin.external_id);
//実行結果を確認
{
expect(resWorktypes.worktypes.length).toBe(0);
}
});
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);
await createWorktype(source, account.id, 'worktype1', 'description1');
await createWorktype(source, account.id, 'worktype2');
//作成したデータを確認
const worktypes = await getWorktypes(source, account.id);
{
expect(worktypes.length).toBe(2);
expect(worktypes[0].custom_worktype_id).toBe('worktype1');
expect(worktypes[1].custom_worktype_id).toBe('worktype2');
expect(worktypes[0].description).toBe('description1');
expect(worktypes[1].description).toBeNull();
}
//DBアクセスに失敗するようにする
const worktypeService = module.get<WorktypesRepositoryService>(
WorktypesRepositoryService,
);
worktypeService.getWorktypes = jest.fn().mockRejectedValue('DB failed');
try {
await service.getWorktypes(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();
}
}
});
});

View File

@ -22,6 +22,7 @@ import {
Dealer, Dealer,
GetMyAccountResponse, GetMyAccountResponse,
GetTypistGroupResponse, GetTypistGroupResponse,
GetWorktypesResponse,
} from './types/types'; } from './types/types';
import { import {
DateWithZeroTime, DateWithZeroTime,
@ -45,6 +46,7 @@ import {
TypistGroupNotExistError, TypistGroupNotExistError,
TypistIdInvalidError, TypistIdInvalidError,
} from '../../repositories/user_groups/errors/types'; } from '../../repositories/user_groups/errors/types';
import { WorktypesRepositoryService } from '../../repositories/worktypes/worktypes.repository.service';
@Injectable() @Injectable()
export class AccountsService { export class AccountsService {
@ -53,6 +55,7 @@ export class AccountsService {
private readonly licensesRepository: LicensesRepositoryService, private readonly licensesRepository: LicensesRepositoryService,
private readonly usersRepository: UsersRepositoryService, private readonly usersRepository: UsersRepositoryService,
private readonly userGroupsRepository: UserGroupsRepositoryService, private readonly userGroupsRepository: UserGroupsRepositoryService,
private readonly worktypesRepository: WorktypesRepositoryService,
private readonly adB2cService: AdB2cService, private readonly adB2cService: AdB2cService,
private readonly sendgridService: SendGridService, private readonly sendgridService: SendGridService,
private readonly blobStorageService: BlobstorageService, private readonly blobStorageService: BlobstorageService,
@ -1049,4 +1052,43 @@ export class AccountsService {
); );
} }
} }
/**
*
* @param context
* @param externalId
* @returns worktypes
*/
async getWorktypes(
context: Context,
externalId: string,
): Promise<GetWorktypesResponse> {
this.logger.log(`[IN] [${context.trackingId}] ${this.getWorktypes.name}`);
try {
// 外部IDをもとにユーザー情報を取得する
const { account_id: accountId } =
await this.usersRepository.findUserByExternalId(externalId);
// ワークタイプ一覧を取得する
const worktypes = await this.worktypesRepository.getWorktypes(accountId);
return {
worktypes: worktypes.map((x) => ({
id: x.id,
worktypeId: x.custom_worktype_id,
description: x.description ?? undefined,
})),
};
} catch (e) {
this.logger.error(e);
throw new HttpException(
makeErrorResponse('E009999'),
HttpStatus.INTERNAL_SERVER_ERROR,
);
} finally {
this.logger.log(
`[OUT] [${context.trackingId}] ${this.getWorktypes.name}`,
);
}
}
} }

View File

@ -16,6 +16,12 @@ import { AdB2cUser } from '../../../gateways/adb2c/types/types';
import { LicensesRepositoryService } from '../../../repositories/licenses/licenses.repository.service'; import { LicensesRepositoryService } from '../../../repositories/licenses/licenses.repository.service';
import { Context } from '../../../common/log'; import { Context } from '../../../common/log';
import { BlobstorageService } from '../../../gateways/blobstorage/blobstorage.service'; import { BlobstorageService } from '../../../gateways/blobstorage/blobstorage.service';
import { Worktype } from '../../../repositories/worktypes/entity/worktype.entity';
import { WorktypesRepositoryService } from '../../../repositories/worktypes/worktypes.repository.service';
export type WorktypesRepositoryMockValue = {
getWorktypes: Worktype[] | Error;
};
export type LicensesRepositoryMockValue = { export type LicensesRepositoryMockValue = {
getLicenseOrderHistoryInfo: getLicenseOrderHistoryInfo:
@ -79,6 +85,7 @@ export const makeAccountsServiceMock = async (
sendGridMockValue: SendGridMockValue, sendGridMockValue: SendGridMockValue,
blobStorageMockValue: BlobStorageServiceMockValue, blobStorageMockValue: BlobStorageServiceMockValue,
licensesRepositoryMockValue: LicensesRepositoryMockValue, licensesRepositoryMockValue: LicensesRepositoryMockValue,
worktypesRepositoryMockValue: WorktypesRepositoryMockValue,
): Promise<AccountsService> => { ): Promise<AccountsService> => {
const module: TestingModule = await Test.createTestingModule({ const module: TestingModule = await Test.createTestingModule({
providers: [AccountsService], providers: [AccountsService],
@ -107,6 +114,8 @@ export const makeAccountsServiceMock = async (
return makeBlobStorageServiceMock(blobStorageMockValue); return makeBlobStorageServiceMock(blobStorageMockValue);
case LicensesRepositoryService: case LicensesRepositoryService:
return makeLicensesRepositoryMock(licensesRepositoryMockValue); return makeLicensesRepositoryMock(licensesRepositoryMockValue);
case WorktypesRepositoryService:
return makeWorktypesRepositoryMock(worktypesRepositoryMockValue);
} }
}) })
.compile(); .compile();
@ -114,6 +123,19 @@ export const makeAccountsServiceMock = async (
return module.get<AccountsService>(AccountsService); return module.get<AccountsService>(AccountsService);
}; };
export const makeWorktypesRepositoryMock = (
value: WorktypesRepositoryMockValue,
) => {
const { getWorktypes } = value;
return {
getWorktypes:
getWorktypes instanceof Error
? jest.fn<Promise<void>, []>().mockRejectedValue(getWorktypes)
: jest.fn<Promise<Worktype[]>, []>().mockResolvedValue(getWorktypes),
};
};
export const makeAccountsRepositoryMock = ( export const makeAccountsRepositoryMock = (
value: AccountsRepositoryMockValue, value: AccountsRepositoryMockValue,
) => { ) => {
@ -295,6 +317,13 @@ export const makeBlobStorageServiceMock = (
}; };
// 個別のテストケースに対応してそれぞれのMockを用意するのは無駄が多いのでテストケース内で個別の値を設定する // 個別のテストケースに対応してそれぞれのMockを用意するのは無駄が多いのでテストケース内で個別の値を設定する
export const makeDefaultWorktypesRepositoryMockValue =
(): WorktypesRepositoryMockValue => {
return {
getWorktypes: [],
};
};
export const makeDefaultAccountsRepositoryMockValue = export const makeDefaultAccountsRepositoryMockValue =
(): AccountsRepositoryMockValue => { (): AccountsRepositoryMockValue => {
let licenseSummaryInfo = new LicenseSummaryInfo(); let licenseSummaryInfo = new LicenseSummaryInfo();

View File

@ -6,6 +6,7 @@ import {
import { SortCriteria } from '../../../repositories/sort_criteria/entity/sort_criteria.entity'; import { SortCriteria } from '../../../repositories/sort_criteria/entity/sort_criteria.entity';
import { UserGroup } from '../../../repositories/user_groups/entity/user_group.entity'; import { UserGroup } from '../../../repositories/user_groups/entity/user_group.entity';
import { UserGroupMember } from '../../../repositories/user_groups/entity/user_group_member.entity'; import { UserGroupMember } from '../../../repositories/user_groups/entity/user_group_member.entity';
import { Worktype } from '../../../repositories/worktypes/entity/worktype.entity';
/** /**
* ユーティリティ: すべてのソート条件を取得する * ユーティリティ: すべてのソート条件を取得する
@ -108,3 +109,36 @@ export const getTypistGroupMember = async (
}, },
}); });
}; };
// Worktypeを作成する
export const createWorktype = async (
datasource: DataSource,
accountId: number,
worktypeId: string,
description?: string,
): Promise<Worktype> => {
const { identifiers } = await datasource.getRepository(Worktype).insert({
account_id: accountId,
custom_worktype_id: worktypeId,
description: description ?? null,
deleted_at: null,
created_by: 'test_runner',
created_at: new Date(),
updated_by: 'updater',
updated_at: new Date(),
});
const worktype = identifiers.pop() as Worktype;
return worktype;
};
// Worktypeを取得する
export const getWorktypes = async (
datasource: DataSource,
accountId: number,
): Promise<Worktype[]> => {
return await datasource.getRepository(Worktype).find({
where: {
account_id: accountId,
},
});
};

View File

@ -333,18 +333,18 @@ export class CancelIssueRequest {
export class CancelIssueResponse {} export class CancelIssueResponse {}
export class WorkType { export class Worktype {
@ApiProperty({ description: 'WorkTypeのID' }) @ApiProperty({ description: 'WorktypeのID' })
id: number; id: number;
@ApiProperty({ description: 'WorkTypeID' }) @ApiProperty({ description: 'WorktypeID' })
workTypeId: string; worktypeId: string;
@ApiProperty({ description: 'WorkTypeの説明', required: false }) @ApiProperty({ description: 'Worktypeの説明', required: false })
description?: string; description?: string;
} }
export class GetWorkTypesResponse { export class GetWorktypesResponse {
@ApiProperty({ type: [WorkType] }) @ApiProperty({ type: [Worktype] })
workTypes: WorkType[]; worktypes: Worktype[];
} }
export class CreateWorktypesRequest { export class CreateWorktypesRequest {

View File

@ -0,0 +1,38 @@
import { Account } from '../../accounts/entity/account.entity';
import {
Entity,
Column,
PrimaryGeneratedColumn,
CreateDateColumn,
UpdateDateColumn,
} from 'typeorm';
@Entity({ name: 'worktypes' })
export class Worktype {
@PrimaryGeneratedColumn()
id: number;
@Column()
account_id: number;
@Column()
custom_worktype_id: string;
@Column({ nullable: true })
description?: string;
@Column({ nullable: true })
deleted_at?: Date;
@Column({ nullable: true })
created_by: string;
@CreateDateColumn({ default: () => "datetime('now', 'localtime')" }) // defaultはSQLite用設定値.本番用は別途migrationで設定
created_at: Date;
@Column({ nullable: true })
updated_by?: string;
@UpdateDateColumn({ default: () => "datetime('now', 'localtime')" }) // defaultはSQLite用設定値.本番用は別途migrationで設定
updated_at: Date;
}

View File

@ -0,0 +1 @@

View File

@ -0,0 +1,11 @@
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { Worktype } from './entity/worktype.entity';
import { WorktypesRepositoryService } from './worktypes.repository.service';
@Module({
imports: [TypeOrmModule.forFeature([Worktype])],
providers: [WorktypesRepositoryService],
exports: [WorktypesRepositoryService],
})
export class WorktypesRepositoryModule {}

View File

@ -0,0 +1,22 @@
import { Injectable } from '@nestjs/common';
import { DataSource } from 'typeorm';
import { Worktype } from './entity/worktype.entity';
@Injectable()
export class WorktypesRepositoryService {
constructor(private dataSource: DataSource) {}
/**
*
* @param accountId
* @returns worktypes
*/
async getWorktypes(accountId: number): Promise<Worktype[]> {
return await this.dataSource.transaction(async (entityManager) => {
const repo = entityManager.getRepository(Worktype);
const worktypes = await repo.find({ where: { account_id: accountId } });
return worktypes;
});
}
}