결재 템플릿 단계 적용 구현

- ApprovalTemplate 엔티티·DTO·원격 리포지토리 추가
- ApprovalController에 템플릿 로딩/적용 상태와 assignSteps 호출 연동
- ApprovalPage 단계 탭에 템플릿 선택 UI 및 적용 확인 다이얼로그 구현
- 템플릿 적용 단위 테스트와 IMPLEMENTATION_TASKS 현황 갱신
This commit is contained in:
JiWoong Sul
2025-09-25 00:21:12 +09:00
parent b6e50464d2
commit c3010965ad
63 changed files with 10179 additions and 1436 deletions

View File

@@ -0,0 +1,113 @@
/// 그룹-메뉴 권한 엔티티
///
/// - 그룹과 메뉴별 CRUD 권한을 표현한다.
/// - presentation/data 레이어 세부 사항에 의존하지 않는다.
class GroupPermission {
GroupPermission({
this.id,
required this.group,
required this.menu,
this.canCreate = false,
this.canRead = true,
this.canUpdate = false,
this.canDelete = false,
this.isActive = true,
this.isDeleted = false,
this.note,
this.createdAt,
this.updatedAt,
});
final int? id;
final GroupPermissionGroup group;
final GroupPermissionMenu menu;
final bool canCreate;
final bool canRead;
final bool canUpdate;
final bool canDelete;
final bool isActive;
final bool isDeleted;
final String? note;
final DateTime? createdAt;
final DateTime? updatedAt;
GroupPermission copyWith({
int? id,
GroupPermissionGroup? group,
GroupPermissionMenu? menu,
bool? canCreate,
bool? canRead,
bool? canUpdate,
bool? canDelete,
bool? isActive,
bool? isDeleted,
String? note,
DateTime? createdAt,
DateTime? updatedAt,
}) {
return GroupPermission(
id: id ?? this.id,
group: group ?? this.group,
menu: menu ?? this.menu,
canCreate: canCreate ?? this.canCreate,
canRead: canRead ?? this.canRead,
canUpdate: canUpdate ?? this.canUpdate,
canDelete: canDelete ?? this.canDelete,
isActive: isActive ?? this.isActive,
isDeleted: isDeleted ?? this.isDeleted,
note: note ?? this.note,
createdAt: createdAt ?? this.createdAt,
updatedAt: updatedAt ?? this.updatedAt,
);
}
}
class GroupPermissionGroup {
GroupPermissionGroup({required this.id, required this.groupName});
final int id;
final String groupName;
}
class GroupPermissionMenu {
GroupPermissionMenu({required this.id, required this.menuName});
final int id;
final String menuName;
}
/// 그룹 권한 생성/수정 입력 모델
class GroupPermissionInput {
GroupPermissionInput({
required this.groupId,
required this.menuId,
this.canCreate = false,
this.canRead = true,
this.canUpdate = false,
this.canDelete = false,
this.isActive = true,
this.note,
});
final int groupId;
final int menuId;
final bool canCreate;
final bool canRead;
final bool canUpdate;
final bool canDelete;
final bool isActive;
final String? note;
Map<String, dynamic> toPayload() {
return {
'group_id': groupId,
'menu_id': menuId,
'can_create': canCreate,
'can_read': canRead,
'can_update': canUpdate,
'can_delete': canDelete,
'is_active': isActive,
'note': note,
};
}
}