Merge branch 'develop' into ccb

This commit is contained in:
makabe 2024-02-05 16:36:09 +09:00
commit 8e159a1c2a
10 changed files with 165 additions and 64 deletions

View File

@ -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 && (

View File

@ -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 {

View File

@ -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";

View File

@ -571,4 +571,4 @@
"close": "Schließen"
}
}
}
}

View File

@ -571,4 +571,4 @@
"close": "Close"
}
}
}
}

View File

@ -571,4 +571,4 @@
"close": "Cerrar"
}
}
}
}

View File

@ -571,4 +571,4 @@
"close": "Fermer"
}
}
}
}

View 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`;

View File

@ -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}`);

View File

@ -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) {