Merge branch 'develop' into ccb
This commit is contained in:
commit
8e159a1c2a
@ -191,23 +191,32 @@ const AccountPage: React.FC = (): JSX.Element => {
|
||||
)}
|
||||
</dt>
|
||||
{isTier5 && (
|
||||
<dd>
|
||||
{/* eslint-disable-next-line jsx-a11y/label-has-associated-control */}
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
className={styles.formCheck}
|
||||
checked={updateAccountInfo.delegationPermission}
|
||||
onChange={(e) => {
|
||||
dispatch(
|
||||
changeDealerPermission({
|
||||
delegationPermission: e.target.checked,
|
||||
})
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</label>
|
||||
</dd>
|
||||
<>
|
||||
<dd>
|
||||
{/* eslint-disable-next-line jsx-a11y/label-has-associated-control */}
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
className={styles.formCheck}
|
||||
checked={updateAccountInfo.delegationPermission}
|
||||
onChange={(e) => {
|
||||
dispatch(
|
||||
changeDealerPermission({
|
||||
delegationPermission: e.target.checked,
|
||||
})
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</label>
|
||||
</dd>
|
||||
<dd className={`${styles.full} ${styles.formComment}`}>
|
||||
{t(
|
||||
getTranslationID(
|
||||
"accountPage.text.dealerManagementAnnotation"
|
||||
)
|
||||
)}
|
||||
</dd>
|
||||
</>
|
||||
)}
|
||||
{!isTier5 && <dd>-</dd>}
|
||||
</dl>
|
||||
@ -374,6 +383,15 @@ const AccountPage: React.FC = (): JSX.Element => {
|
||||
className={styles.icLoading}
|
||||
alt="Loading"
|
||||
/>
|
||||
{isTier5 && (
|
||||
<p className={styles.formComment}>
|
||||
{t(
|
||||
getTranslationID(
|
||||
"accountPage.text.dealerManagementAnnotation"
|
||||
)
|
||||
)}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{isTier5 && (
|
||||
|
||||
@ -1632,8 +1632,31 @@ _:-ms-lang(x)::-ms-backdrop,
|
||||
.account .listVertical dd .formInput {
|
||||
max-width: 100%;
|
||||
}
|
||||
.account .listVertical dd.full {
|
||||
width: 100%;
|
||||
padding-top: 0;
|
||||
background: none;
|
||||
}
|
||||
.account .listVertical dd.full.odd {
|
||||
background: #f5f5f5;
|
||||
}
|
||||
.account .listVertical dd.formComment {
|
||||
text-align: left;
|
||||
font-size: 0.9rem;
|
||||
word-break: break-word;
|
||||
}
|
||||
.account .box100 .formComment {
|
||||
display: block;
|
||||
width: 600px;
|
||||
text-align: left;
|
||||
}
|
||||
.account .box100.alignRight {
|
||||
width: calc(1200px + 3rem);
|
||||
text-align: right;
|
||||
}
|
||||
.account .box100.alignRight .formComment {
|
||||
margin-left: 648px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.menuAction {
|
||||
@ -2306,7 +2329,8 @@ tr.isSelected .menuInTable li a.isDisable {
|
||||
}
|
||||
.formChange ul.chooseMember li input + label:hover,
|
||||
.formChange ul.holdMember li input + label:hover {
|
||||
background: #e6e6e6 url(../assets/images/arrow_circle_left.svg) no-repeat left center;
|
||||
background: #e6e6e6 url(../assets/images/arrow_circle_left.svg) no-repeat left
|
||||
center;
|
||||
background-size: 1.3rem;
|
||||
}
|
||||
.formChange ul.chooseMember li input:checked + label,
|
||||
@ -2317,8 +2341,8 @@ tr.isSelected .menuInTable li a.isDisable {
|
||||
}
|
||||
.formChange ul.chooseMember li input:checked + label:hover,
|
||||
.formChange ul.holdMember li input:checked + label:hover {
|
||||
background: #e6e6e6 url(../assets/images/arrow_circle_right.svg) no-repeat right
|
||||
center;
|
||||
background: #e6e6e6 url(../assets/images/arrow_circle_right.svg) no-repeat
|
||||
right center;
|
||||
background-size: 1.3rem;
|
||||
}
|
||||
.formChange > p {
|
||||
@ -2471,7 +2495,8 @@ tr.isSelected .menuInTable li a.isDisable {
|
||||
}
|
||||
.formChange ul.chooseMember li input + label:hover,
|
||||
.formChange ul.holdMember li input + label:hover {
|
||||
background: #e6e6e6 url(../assets/images/arrow_circle_left.svg) no-repeat left center;
|
||||
background: #e6e6e6 url(../assets/images/arrow_circle_left.svg) no-repeat left
|
||||
center;
|
||||
background-size: 1.3rem;
|
||||
}
|
||||
.formChange ul.chooseMember li input:checked + label,
|
||||
@ -2482,8 +2507,8 @@ tr.isSelected .menuInTable li a.isDisable {
|
||||
}
|
||||
.formChange ul.chooseMember li input:checked + label:hover,
|
||||
.formChange ul.holdMember li input:checked + label:hover {
|
||||
background: #e6e6e6 url(../assets/images/arrow_circle_right.svg) no-repeat right
|
||||
center;
|
||||
background: #e6e6e6 url(../assets/images/arrow_circle_right.svg) no-repeat
|
||||
right center;
|
||||
background-size: 1.3rem;
|
||||
}
|
||||
.formChange > p {
|
||||
|
||||
@ -107,6 +107,7 @@ declare const classNames: {
|
||||
readonly clm0: "clm0";
|
||||
readonly menuInTable: "menuInTable";
|
||||
readonly isSelected: "isSelected";
|
||||
readonly odd: "odd";
|
||||
readonly alignRight: "alignRight";
|
||||
readonly menuAction: "menuAction";
|
||||
readonly inTable: "inTable";
|
||||
|
||||
@ -571,4 +571,4 @@
|
||||
"close": "Schließen"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -571,4 +571,4 @@
|
||||
"close": "Close"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -571,4 +571,4 @@
|
||||
"close": "Cerrar"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -571,4 +571,4 @@
|
||||
"close": "Fermer"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
27
dictation_server/db/migrations/056-add_tasks_index.sql
Normal file
27
dictation_server/db/migrations/056-add_tasks_index.sql
Normal file
@ -0,0 +1,27 @@
|
||||
-- +migrate Up
|
||||
ALTER TABLE `tasks` ADD INDEX `idx_tasks_audio_file_id` (audio_file_id);
|
||||
ALTER TABLE `tasks` ADD INDEX `idx_tasks_status` (status);
|
||||
ALTER TABLE `tasks` ADD INDEX `idx_tasks_typist_user_id` (typist_user_id);
|
||||
ALTER TABLE `tasks` ADD INDEX `idx_tasks_is_job_number_enabled` (is_job_number_enabled);
|
||||
ALTER TABLE `checkout_permission` ADD INDEX `idx_checkout_permission_task_id` (task_id);
|
||||
ALTER TABLE `checkout_permission` ADD INDEX `idx_checkout_permission_user_group_id` (user_group_id);
|
||||
ALTER TABLE `checkout_permission` ADD INDEX `idx_checkout_permission_user_id` (user_id);
|
||||
ALTER TABLE `users` ADD INDEX `idx_users_role` (role);
|
||||
ALTER TABLE `users` ADD INDEX `idx_users_author_id` (author_id);
|
||||
ALTER TABLE `users` ADD INDEX `idx_users_deleted_at` (deleted_at);
|
||||
ALTER TABLE `worktypes` ADD INDEX `idx_worktypes_custom_worktype_id` (custom_worktype_id);
|
||||
ALTER TABLE `workflows` ADD INDEX `idx_workflows_account_id` (account_id);
|
||||
|
||||
-- +migrate Down
|
||||
ALTER TABLE `tasks` DROP INDEX `idx_tasks_audio_file_id`;
|
||||
ALTER TABLE `tasks` DROP INDEX `idx_tasks_status`;
|
||||
ALTER TABLE `tasks` DROP INDEX `idx_tasks_typist_user_id`;
|
||||
ALTER TABLE `tasks` DROP INDEX `idx_tasks_is_job_number_enabled`;
|
||||
ALTER TABLE `checkout_permission` DROP INDEX `idx_checkout_permission_task_id`;
|
||||
ALTER TABLE `checkout_permission` DROP INDEX `idx_checkout_permission_user_group_id`;
|
||||
ALTER TABLE `checkout_permission` DROP INDEX `idx_checkout_permission_user_id`;
|
||||
ALTER TABLE `users` DROP INDEX `idx_users_role`;
|
||||
ALTER TABLE `users` DROP INDEX `idx_users_author_id`;
|
||||
ALTER TABLE `users` DROP INDEX `idx_users_deleted_at`;
|
||||
ALTER TABLE `worktypes` DROP INDEX `idx_worktypes_custom_worktype_id`;
|
||||
ALTER TABLE `workflows` DROP INDEX `idx_workflows_account_id`;
|
||||
@ -194,6 +194,7 @@ export class TasksRepositoryService {
|
||||
audio_file_id: audio_file_id,
|
||||
},
|
||||
comment: `${context.getTrackingId()}_${new Date().toUTCString()}`,
|
||||
lock: { mode: 'pessimistic_write' },
|
||||
});
|
||||
if (!task) {
|
||||
throw new TasksNotFoundError(
|
||||
@ -209,6 +210,7 @@ export class TasksRepositoryService {
|
||||
typist_user_id: user_id,
|
||||
},
|
||||
comment: `${context.getTrackingId()}_${new Date().toUTCString()}`,
|
||||
lock: { mode: 'pessimistic_write' },
|
||||
});
|
||||
|
||||
if (tasks.length > 0) {
|
||||
@ -247,6 +249,7 @@ export class TasksRepositoryService {
|
||||
},
|
||||
},
|
||||
comment: `${context.getTrackingId()}_${new Date().toUTCString()}`,
|
||||
lock: { mode: 'pessimistic_write' },
|
||||
});
|
||||
// ユーザーの所属するすべてのグループIDを列挙
|
||||
const groupIds = groups.map((member) => member.user_group_id);
|
||||
@ -269,6 +272,7 @@ export class TasksRepositoryService {
|
||||
},
|
||||
],
|
||||
comment: `${context.getTrackingId()}_${new Date().toUTCString()}`,
|
||||
lock: { mode: 'pessimistic_write' },
|
||||
});
|
||||
|
||||
//チェックアウト権限がなければエラー
|
||||
@ -339,6 +343,7 @@ export class TasksRepositoryService {
|
||||
audio_file_id: audio_file_id,
|
||||
},
|
||||
comment: `${context.getTrackingId()}_${new Date().toUTCString()}`,
|
||||
lock: { mode: 'pessimistic_write' },
|
||||
});
|
||||
if (!task) {
|
||||
throw new TasksNotFoundError(
|
||||
@ -392,6 +397,7 @@ export class TasksRepositoryService {
|
||||
audio_file_id: audio_file_id,
|
||||
},
|
||||
comment: `${context.getTrackingId()}_${new Date().toUTCString()}`,
|
||||
lock: { mode: 'pessimistic_write' },
|
||||
});
|
||||
if (!task) {
|
||||
throw new TasksNotFoundError(
|
||||
@ -467,6 +473,7 @@ export class TasksRepositoryService {
|
||||
audio_file_id: audio_file_id,
|
||||
},
|
||||
comment: `${context.getTrackingId()}_${new Date().toUTCString()}`,
|
||||
lock: { mode: 'pessimistic_write' },
|
||||
});
|
||||
if (!task) {
|
||||
throw new TasksNotFoundError(
|
||||
@ -518,6 +525,7 @@ export class TasksRepositoryService {
|
||||
audio_file_id: audio_file_id,
|
||||
},
|
||||
comment: `${context.getTrackingId()}_${new Date().toUTCString()}`,
|
||||
lock: { mode: 'pessimistic_write' },
|
||||
});
|
||||
if (!task) {
|
||||
throw new TasksNotFoundError(
|
||||
@ -901,6 +909,7 @@ export class TasksRepositoryService {
|
||||
where: { account_id: account_id, is_job_number_enabled: true },
|
||||
order: { created_at: 'DESC', job_number: 'DESC' },
|
||||
comment: `${context.getTrackingId()}_${new Date().toUTCString()}`,
|
||||
lock: { mode: 'pessimistic_write' },
|
||||
});
|
||||
|
||||
let newJobNumber = '00000001';
|
||||
@ -963,30 +972,6 @@ export class TasksRepositoryService {
|
||||
assignees: Assignee[],
|
||||
): Promise<void> {
|
||||
await this.dataSource.transaction(async (entityManager) => {
|
||||
// UserGroupの取得/存在確認
|
||||
const userGroupIds = assignees
|
||||
.filter((x) => x.typistGroupId !== undefined)
|
||||
.map((y) => {
|
||||
return y.typistGroupId;
|
||||
});
|
||||
const groupRepo = entityManager.getRepository(UserGroup);
|
||||
const groupRecords = await groupRepo.find({
|
||||
where: {
|
||||
id: In(userGroupIds),
|
||||
account_id: account_id,
|
||||
deleted_at: IsNull(),
|
||||
},
|
||||
comment: `${context.getTrackingId()}_${new Date().toUTCString()}`,
|
||||
});
|
||||
// idはユニークであるため取得件数の一致でグループの存在を確認
|
||||
if (userGroupIds.length !== groupRecords.length) {
|
||||
throw new TypistUserGroupNotFoundError(
|
||||
`Group not exists Error. reqUserGroupId:${userGroupIds}; resUserGroupId:${groupRecords.map(
|
||||
(x) => x.id,
|
||||
)}`,
|
||||
);
|
||||
}
|
||||
|
||||
// Userの取得/存在確認
|
||||
const typistUserIds = assignees
|
||||
.filter((x) => x.typistUserId !== undefined)
|
||||
@ -1014,6 +999,31 @@ export class TasksRepositoryService {
|
||||
);
|
||||
}
|
||||
|
||||
// UserGroupの取得/存在確認
|
||||
const userGroupIds = assignees
|
||||
.filter((x) => x.typistGroupId !== undefined)
|
||||
.map((y) => {
|
||||
return y.typistGroupId;
|
||||
});
|
||||
const groupRepo = entityManager.getRepository(UserGroup);
|
||||
const groupRecords = await groupRepo.find({
|
||||
where: {
|
||||
id: In(userGroupIds),
|
||||
account_id: account_id,
|
||||
deleted_at: IsNull(),
|
||||
},
|
||||
comment: `${context.getTrackingId()}_${new Date().toUTCString()}`,
|
||||
lock: { mode: 'pessimistic_write' },
|
||||
});
|
||||
// idはユニークであるため取得件数の一致でグループの存在を確認
|
||||
if (userGroupIds.length !== groupRecords.length) {
|
||||
throw new TypistUserGroupNotFoundError(
|
||||
`Group not exists Error. reqUserGroupId:${userGroupIds}; resUserGroupId:${groupRecords.map(
|
||||
(x) => x.id,
|
||||
)}`,
|
||||
);
|
||||
}
|
||||
|
||||
// 引数audioFileIdを使ってTaskレコードを特定し、そのステータスを取得/存在確認
|
||||
const taskRepo = entityManager.getRepository(Task);
|
||||
|
||||
@ -1029,6 +1039,7 @@ export class TasksRepositoryService {
|
||||
},
|
||||
},
|
||||
comment: `${context.getTrackingId()}_${new Date().toUTCString()}`,
|
||||
lock: { mode: 'pessimistic_write' },
|
||||
});
|
||||
//タスクが存在しない or ステータスがUploadedでなければエラー
|
||||
if (!taskRecord) {
|
||||
@ -1192,39 +1203,51 @@ export class TasksRepositoryService {
|
||||
return await this.dataSource.transaction(async (entityManager) => {
|
||||
// 音声ファイルを取得
|
||||
const audioFileRepo = entityManager.getRepository(AudioFile);
|
||||
const audioFile = await audioFileRepo.findOne({
|
||||
relations: {
|
||||
task: true,
|
||||
},
|
||||
const audio = await audioFileRepo.findOne({
|
||||
where: {
|
||||
id: audioFileId,
|
||||
account_id: accountId,
|
||||
},
|
||||
comment: `${context.getTrackingId()}_${new Date().toUTCString()}`,
|
||||
});
|
||||
if (!audioFile) {
|
||||
if (!audio) {
|
||||
throw new Error(
|
||||
`audio file not found. audio_file_id:${audioFileId}, accountId:${accountId}`,
|
||||
);
|
||||
}
|
||||
|
||||
const { task } = audioFile;
|
||||
|
||||
if (!task) {
|
||||
throw new Error(
|
||||
`task not found. audio_file_id:${audioFileId}, accountId:${accountId}`,
|
||||
);
|
||||
}
|
||||
// authorIdをもとにユーザーを取得
|
||||
const userRepo = entityManager.getRepository(User);
|
||||
const authorUser = await userRepo.findOne({
|
||||
where: {
|
||||
author_id: audioFile.author_id,
|
||||
author_id: audio.author_id,
|
||||
account_id: accountId,
|
||||
},
|
||||
comment: `${context.getTrackingId()}_${new Date().toUTCString()}`,
|
||||
lock: { mode: 'pessimistic_write' },
|
||||
});
|
||||
|
||||
// TaskとFileを取得
|
||||
const taskRepo = entityManager.getRepository(Task);
|
||||
const task = await taskRepo.findOne({
|
||||
relations: {
|
||||
file: true,
|
||||
},
|
||||
where: {
|
||||
account_id: accountId,
|
||||
audio_file_id: audioFileId,
|
||||
},
|
||||
comment: `${context.getTrackingId()}_${new Date().toUTCString()}`,
|
||||
lock: { mode: 'pessimistic_write' },
|
||||
});
|
||||
|
||||
const audioFile = task?.file;
|
||||
if (!audioFile) {
|
||||
throw new Error(
|
||||
`audio file not found. audio_file_id:${audioFileId}, accountId:${accountId}`,
|
||||
);
|
||||
}
|
||||
|
||||
// 音声ファイル上のworktypeIdをもとにworktypeを取得
|
||||
const worktypeRepo = entityManager.getRepository(Worktype);
|
||||
const worktypeRecord = await worktypeRepo.findOne({
|
||||
@ -1233,6 +1256,7 @@ export class TasksRepositoryService {
|
||||
account_id: accountId,
|
||||
},
|
||||
comment: `${context.getTrackingId()}_${new Date().toUTCString()}`,
|
||||
lock: { mode: 'pessimistic_write' },
|
||||
});
|
||||
|
||||
// 音声ファイル上のworktypeIdが設定されているが、一致するworktypeが存在しない場合はエラーを出して終了
|
||||
@ -1254,6 +1278,7 @@ export class TasksRepositoryService {
|
||||
worktype_id: worktypeRecord?.id ?? IsNull(),
|
||||
},
|
||||
comment: `${context.getTrackingId()}_${new Date().toUTCString()}`,
|
||||
lock: { mode: 'pessimistic_write' },
|
||||
});
|
||||
|
||||
// Workflow(ルーティングルール)があればタスクのチェックアウト権限を設定する
|
||||
@ -1281,6 +1306,7 @@ export class TasksRepositoryService {
|
||||
account_id: accountId,
|
||||
},
|
||||
comment: `${context.getTrackingId()}_${new Date().toUTCString()}`,
|
||||
lock: { mode: 'pessimistic_write' },
|
||||
});
|
||||
if (!myAuthorUser) {
|
||||
throw new Error(
|
||||
@ -1297,6 +1323,7 @@ export class TasksRepositoryService {
|
||||
worktype_id: worktypeRecord?.id ?? IsNull(),
|
||||
},
|
||||
comment: `${context.getTrackingId()}_${new Date().toUTCString()}`,
|
||||
lock: { mode: 'pessimistic_write' },
|
||||
});
|
||||
|
||||
// API実行者のAuthorIdと音声ファイルのWorktypeをもとにルーティングルールを取得できない場合はエラーを出して終了
|
||||
@ -1478,6 +1505,7 @@ export class TasksRepositoryService {
|
||||
const typistUsers = await userRepo.find({
|
||||
where: { account_id: accountId, id: In(typistIds) },
|
||||
comment: `${context.getTrackingId()}_${new Date().toUTCString()}`,
|
||||
lock: { mode: 'pessimistic_write' },
|
||||
});
|
||||
if (typistUsers.length !== typistIds.length) {
|
||||
throw new Error(`typist not found. ids: ${typistIds}`);
|
||||
@ -1491,6 +1519,7 @@ export class TasksRepositoryService {
|
||||
const typistGroups = await userGroupRepo.find({
|
||||
where: { account_id: accountId, id: In(groupIds) },
|
||||
comment: `${context.getTrackingId()}_${new Date().toUTCString()}`,
|
||||
lock: { mode: 'pessimistic_write' },
|
||||
});
|
||||
if (typistGroups.length !== groupIds.length) {
|
||||
throw new Error(`typist group not found. ids: ${groupIds}`);
|
||||
|
||||
@ -220,6 +220,7 @@ export class WorktypesRepositoryService {
|
||||
const worktype = await worktypeRepo.findOne({
|
||||
where: { account_id: accountId, id: id },
|
||||
comment: `${context.getTrackingId()}_${new Date().toUTCString()}`,
|
||||
lock: { mode: 'pessimistic_write' },
|
||||
});
|
||||
// ワークタイプが存在しない場合はエラー
|
||||
if (!worktype) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user