diff --git a/dictation_client/src/common/errors/code.ts b/dictation_client/src/common/errors/code.ts index 336b41d..5aa1497 100644 --- a/dictation_client/src/common/errors/code.ts +++ b/dictation_client/src/common/errors/code.ts @@ -54,6 +54,8 @@ export const errorCodes = [ "E010809", // ライセンス発行キャンセル不可エラー(ステータスが変えられている場合) "E010810", // ライセンス発行キャンセル不可エラー(発行から一定期間経過した場合) "E010811", // ライセンス発行キャンセル不可エラー(発行したライセンスが割り当てされている場合) + "E010908", // タイピストグループ不在エラー + "E010909", // タイピストグループ名重複エラー "E011001", // ワークタイプ重複エラー "E011002", // ワークタイプ登録上限超過エラー "E011003", // ワークタイプ不在エラー diff --git a/dictation_client/src/features/workflow/typistGroup/operations.ts b/dictation_client/src/features/workflow/typistGroup/operations.ts index 8ee85f1..3eebdc6 100644 --- a/dictation_client/src/features/workflow/typistGroup/operations.ts +++ b/dictation_client/src/features/workflow/typistGroup/operations.ts @@ -122,11 +122,17 @@ export const createTypistGroupAsync = createAsyncThunk< } catch (e) { // e ⇒ errorObjectに変換" const error = createErrorObject(e); - - const message = - error.statusCode === 400 - ? getTranslationID("typistGroupSetting.message.groupSaveFailedError") - : getTranslationID("common.message.internalServerError"); + let message = getTranslationID("common.message.internalServerError"); + if (error.code === "E010204") { + message = getTranslationID( + "typistGroupSetting.message.groupSaveFailedError" + ); + } + if (error.code === "E010909") { + message = getTranslationID( + "typistGroupSetting.message.GroupNameAlreadyExistError" + ); + } thunkApi.dispatch( openSnackbar({ @@ -242,10 +248,17 @@ export const updateTypistGroupAsync = createAsyncThunk< // e ⇒ errorObjectに変換" const error = createErrorObject(e); - const message = - error.statusCode === 400 - ? getTranslationID("typistGroupSetting.message.groupSaveFailedError") - : getTranslationID("common.message.internalServerError"); + let message = getTranslationID("common.message.internalServerError"); + if (error.code === "E010204" || error.code === "E010908") { + message = getTranslationID( + "typistGroupSetting.message.groupSaveFailedError" + ); + } + if (error.code === "E010909") { + message = getTranslationID( + "typistGroupSetting.message.GroupNameAlreadyExistError" + ); + } thunkApi.dispatch( openSnackbar({ diff --git a/dictation_client/src/translation/de.json b/dictation_client/src/translation/de.json index c729c87..bff0bba 100644 --- a/dictation_client/src/translation/de.json +++ b/dictation_client/src/translation/de.json @@ -425,7 +425,7 @@ "message": { "selectedTypistEmptyError": "Um eine Transkriptionsgruppe zu speichern, müssen ein oder mehrere Transkriptionisten ausgewählt werden.", "groupSaveFailedError": "Die Transkriptionistengruppe konnte nicht gespeichert werden. Die angezeigten Informationen sind möglicherweise veraltet. Aktualisieren Sie daher bitte den Bildschirm, um den neuesten Status anzuzeigen.", - "GroupNameAlreadyExistError": "(de)TypistGroupの保存に失敗しました。同名のTranscriptionistGroupは登録できません。", + "GroupNameAlreadyExistError": "(de)このTranscriptionistGroup名は既に登録されています。他のTranscriptionistGroup名で登録してください。", "deleteFailedWorkflowAssigned": "(de)TranscriptionistGroupの削除に失敗しました。Workflow画面でルーティングルールから対象TranscriptionistGroupを外してください。", "deleteFailedCheckoutPermissionExisted": "(de)TranscriptionistGroupの削除に失敗しました。Dictation画面でタスクのルーティングから対象TranscriptionistGroupを外してください。" } diff --git a/dictation_client/src/translation/en.json b/dictation_client/src/translation/en.json index dca78c7..e0f1800 100644 --- a/dictation_client/src/translation/en.json +++ b/dictation_client/src/translation/en.json @@ -425,7 +425,7 @@ "message": { "selectedTypistEmptyError": "One or more transcriptonist must be selected to save a transcrption group.", "groupSaveFailedError": "Transcriptionist Group could not be saved. The displayed information may be outdated, so please refresh the screen to see the latest status.", - "GroupNameAlreadyExistError": "TypistGroupの保存に失敗しました。同名のTranscriptionistGroupは登録できません。", + "GroupNameAlreadyExistError": "このTranscriptionistGroup名は既に登録されています。他のTranscriptionistGroup名で登録してください。", "deleteFailedWorkflowAssigned": "TranscriptionistGroupの削除に失敗しました。Workflow画面でルーティングルールから対象TranscriptionistGroupを外してください。", "deleteFailedCheckoutPermissionExisted": "TranscriptionistGroupの削除に失敗しました。Dictation画面でタスクのルーティングから対象TranscriptionistGroupを外してください。" } diff --git a/dictation_client/src/translation/es.json b/dictation_client/src/translation/es.json index 84e0cc9..564958a 100644 --- a/dictation_client/src/translation/es.json +++ b/dictation_client/src/translation/es.json @@ -425,7 +425,7 @@ "message": { "selectedTypistEmptyError": "Se deben seleccionar uno o más transcriptores para guardar un grupo de transcripción.", "groupSaveFailedError": "El grupo transcriptor no se pudo salvar. La información mostrada puede estar desactualizada. Así que actualice la pantalla para ver el estado más reciente.", - "GroupNameAlreadyExistError": "(es)TypistGroupの保存に失敗しました。同名のTranscriptionistGroupは登録できません。", + "GroupNameAlreadyExistError": "(es)このTranscriptionistGroup名は既に登録されています。他のTranscriptionistGroup名で登録してください。", "deleteFailedWorkflowAssigned": "(es)TranscriptionistGroupの削除に失敗しました。Workflow画面でルーティングルールから対象TranscriptionistGroupを外してください。", "deleteFailedCheckoutPermissionExisted": "(es)TranscriptionistGroupの削除に失敗しました。Dictation画面でタスクのルーティングから対象TranscriptionistGroupを外してください。" } diff --git a/dictation_client/src/translation/fr.json b/dictation_client/src/translation/fr.json index c90ad0b..9cbdcd2 100644 --- a/dictation_client/src/translation/fr.json +++ b/dictation_client/src/translation/fr.json @@ -425,7 +425,7 @@ "message": { "selectedTypistEmptyError": "Un ou plusieurs transcripteurs doivent être sélectionnés pour enregistrer un groupe de transcription.", "groupSaveFailedError": "Le groupe de transcriptionniste n'a pas pu être enregistré. Les informations affichées peuvent être obsolètes, veuillez donc actualiser l'écran pour voir le dernier statut.", - "GroupNameAlreadyExistError": "(fr)TypistGroupの保存に失敗しました。同名のTranscriptionistGroupは登録できません。", + "GroupNameAlreadyExistError": "(fr)このTranscriptionistGroup名は既に登録されています。他のTranscriptionistGroup名で登録してください。", "deleteFailedWorkflowAssigned": "(fr)TranscriptionistGroupの削除に失敗しました。Workflow画面でルーティングルールから対象TranscriptionistGroupを外してください。", "deleteFailedCheckoutPermissionExisted": "(fr)TranscriptionistGroupの削除に失敗しました。Dictation画面でタスクのルーティングから対象TranscriptionistGroupを外してください。" } diff --git a/dictation_server/db/migrations/058-add_user_group_unique_constraint.sql b/dictation_server/db/migrations/058-add_user_group_unique_constraint.sql new file mode 100644 index 0000000..c9cb2d6 --- /dev/null +++ b/dictation_server/db/migrations/058-add_user_group_unique_constraint.sql @@ -0,0 +1,6 @@ +-- +migrate Up +ALTER TABLE `user_group` ADD UNIQUE `unique_index_account_id_name` (`account_id`, `name`); + + +-- +migrate Down +ALTER TABLE `user_group` DROP INDEX `unique_index_account_id_name`; diff --git a/dictation_server/src/common/error/code.ts b/dictation_server/src/common/error/code.ts index 8f9dc2f..3c488da 100644 --- a/dictation_server/src/common/error/code.ts +++ b/dictation_server/src/common/error/code.ts @@ -59,6 +59,7 @@ export const ErrorCodes = [ 'E010811', // ライセンス発行キャンセル不可エラー(発行したライセンスが割り当てされている場合) 'E010812', // ライセンス未割当エラー 'E010908', // タイピストグループ不在エラー + 'E010909', // タイピストグループ名重複エラー 'E011001', // ワークタイプ重複エラー 'E011002', // ワークタイプ登録上限超過エラー 'E011003', // ワークタイプ不在エラー diff --git a/dictation_server/src/common/error/message.ts b/dictation_server/src/common/error/message.ts index 0a27cc5..9383694 100644 --- a/dictation_server/src/common/error/message.ts +++ b/dictation_server/src/common/error/message.ts @@ -48,6 +48,7 @@ export const errors: Errors = { E010811: 'Already license allocated Error', E010812: 'License not allocated Error', E010908: 'Typist Group not exist Error', + E010909: 'Typist Group name already exist Error', E011001: 'This WorkTypeID already used Error', E011002: 'WorkTypeID create limit exceeded Error', E011003: 'WorkTypeID not found Error', diff --git a/dictation_server/src/features/accounts/accounts.service.ts b/dictation_server/src/features/accounts/accounts.service.ts index 92b6c77..460d843 100644 --- a/dictation_server/src/features/accounts/accounts.service.ts +++ b/dictation_server/src/features/accounts/accounts.service.ts @@ -60,6 +60,7 @@ import { } from '../../repositories/licenses/errors/types'; import { BlobstorageService } from '../../gateways/blobstorage/blobstorage.service'; import { + TypistGroupNameAlreadyExistError, TypistGroupNotExistError, TypistIdInvalidError, } from '../../repositories/user_groups/errors/types'; @@ -1243,6 +1244,12 @@ export class AccountsService { makeErrorResponse('E010204'), HttpStatus.BAD_REQUEST, ); + // 同名のタイピストグループが存在する場合は400エラーを返す + case TypistGroupNameAlreadyExistError: + throw new HttpException( + makeErrorResponse('E010909'), + HttpStatus.BAD_REQUEST, + ); default: throw new HttpException( makeErrorResponse('E009999'), @@ -1317,6 +1324,12 @@ export class AccountsService { makeErrorResponse('E010908'), HttpStatus.BAD_REQUEST, ); + // 同名のタイピストグループが存在する場合は400エラーを返す + case TypistGroupNameAlreadyExistError: + throw new HttpException( + makeErrorResponse('E010909'), + HttpStatus.BAD_REQUEST, + ); default: throw new HttpException( makeErrorResponse('E009999'), diff --git a/dictation_server/src/repositories/user_groups/errors/types.ts b/dictation_server/src/repositories/user_groups/errors/types.ts index 57aabbb..4a215a7 100644 --- a/dictation_server/src/repositories/user_groups/errors/types.ts +++ b/dictation_server/src/repositories/user_groups/errors/types.ts @@ -12,3 +12,10 @@ export class TypistIdInvalidError extends Error { this.name = 'TypistIdInvalidError'; } } +// 同名のタイピストグループが存在する場合のエラー +export class TypistGroupNameAlreadyExistError extends Error { + constructor(message: string) { + super(message); + this.name = 'TypistGroupNameAlreadyExistError'; + } +} \ No newline at end of file diff --git a/dictation_server/src/repositories/user_groups/user_groups.repository.service.ts b/dictation_server/src/repositories/user_groups/user_groups.repository.service.ts index 050d3e1..a900569 100644 --- a/dictation_server/src/repositories/user_groups/user_groups.repository.service.ts +++ b/dictation_server/src/repositories/user_groups/user_groups.repository.service.ts @@ -1,9 +1,13 @@ import { Injectable } from '@nestjs/common'; -import { DataSource, In, IsNull } from 'typeorm'; +import { DataSource, In, IsNull, Not } from 'typeorm'; import { UserGroup } from './entity/user_group.entity'; import { UserGroupMember } from './entity/user_group_member.entity'; import { User } from '../users/entity/user.entity'; -import { TypistGroupNotExistError, TypistIdInvalidError } from './errors/types'; +import { + TypistGroupNameAlreadyExistError, + TypistGroupNotExistError, + TypistIdInvalidError, +} from './errors/types'; import { USER_ROLES } from '../../constants'; import { insertEntities, @@ -132,6 +136,19 @@ export class UserGroupsRepositoryService { )}`, ); } + // 同名のタイピストグループが存在するか確認する + const sameNameTypistGroup = await userGroupRepo.findOne({ + where: { + name, + account_id: accountId, + }, + comment: `${context.getTrackingId()}_${new Date().toUTCString()}`, + }); + if (sameNameTypistGroup) { + throw new TypistGroupNameAlreadyExistError( + `TypistGroup already exists Error. accountId: ${accountId}; name: ${name}`, + ); + } // userGroupをDBに保存する const userGroup = await insertEntity( UserGroup, @@ -200,6 +217,21 @@ export class UserGroupsRepositoryService { ); } + // 同名のタイピストグループが存在するか確認する + const sameNameTypistGroup = await userGroupRepo.findOne({ + where: { + id: Not(typistGroupId), + name: typistGroupName, + account_id: accountId, + }, + comment: `${context.getTrackingId()}_${new Date().toUTCString()}`, + }); + if (sameNameTypistGroup) { + throw new TypistGroupNameAlreadyExistError( + `TypistGroup already exists Error. accountId: ${accountId}; name: ${typistGroupName}`, + ); + } + // GroupIdが自アカウント内に存在するか確認する const typistGroup = await userGroupRepo.findOne({ where: {