주석화 진행상황 정리하고 핵심 모듈에 한글 주석 추가
This commit is contained in:
@@ -3,6 +3,10 @@ import 'package:superport_v2/core/common/utils/json_utils.dart';
|
||||
|
||||
import '../../domain/entities/approval.dart';
|
||||
|
||||
/// 결재 API 응답을 표현하는 DTO.
|
||||
///
|
||||
/// - 원본 JSON 형식을 유지하면서 도메인 엔티티 변환을 제공한다.
|
||||
/// - 일부 필드는 누락 가능성을 고려하여 기본값을 지정한다.
|
||||
class ApprovalDto {
|
||||
ApprovalDto({
|
||||
this.id,
|
||||
@@ -38,6 +42,7 @@ class ApprovalDto {
|
||||
final DateTime? createdAt;
|
||||
final DateTime? updatedAt;
|
||||
|
||||
/// API 응답 JSON을 [ApprovalDto]로 변환한다.
|
||||
factory ApprovalDto.fromJson(Map<String, dynamic> json) {
|
||||
return ApprovalDto(
|
||||
id: json['id'] as int?,
|
||||
@@ -74,6 +79,7 @@ class ApprovalDto {
|
||||
);
|
||||
}
|
||||
|
||||
/// DTO를 도메인 [Approval] 엔티티로 변환한다.
|
||||
Approval toEntity() => Approval(
|
||||
id: id,
|
||||
approvalNo: approvalNo,
|
||||
@@ -92,6 +98,7 @@ class ApprovalDto {
|
||||
updatedAt: updatedAt,
|
||||
);
|
||||
|
||||
/// 페이징 응답을 파싱해 [PaginatedResult]로 변환한다.
|
||||
static PaginatedResult<Approval> parsePaginated(Map<String, dynamic>? json) {
|
||||
final rawItems = JsonUtils.extractList(json, keys: const ['items']);
|
||||
final items = rawItems
|
||||
@@ -107,6 +114,7 @@ class ApprovalDto {
|
||||
}
|
||||
}
|
||||
|
||||
/// 결재 상태(Status) DTO.
|
||||
class ApprovalStatusDto {
|
||||
ApprovalStatusDto({required this.id, required this.name, this.color});
|
||||
|
||||
@@ -122,9 +130,11 @@ class ApprovalStatusDto {
|
||||
);
|
||||
}
|
||||
|
||||
/// DTO를 [ApprovalStatus]로 변환한다.
|
||||
ApprovalStatus toEntity() => ApprovalStatus(id: id, name: name, color: color);
|
||||
}
|
||||
|
||||
/// 결재 요청자 DTO.
|
||||
class ApprovalRequesterDto {
|
||||
ApprovalRequesterDto({
|
||||
required this.id,
|
||||
@@ -144,10 +154,12 @@ class ApprovalRequesterDto {
|
||||
);
|
||||
}
|
||||
|
||||
/// DTO를 [ApprovalRequester]로 변환한다.
|
||||
ApprovalRequester toEntity() =>
|
||||
ApprovalRequester(id: id, employeeNo: employeeNo, name: name);
|
||||
}
|
||||
|
||||
/// 결재 승인자 DTO.
|
||||
class ApprovalApproverDto {
|
||||
ApprovalApproverDto({
|
||||
required this.id,
|
||||
@@ -167,10 +179,12 @@ class ApprovalApproverDto {
|
||||
);
|
||||
}
|
||||
|
||||
/// DTO를 [ApprovalApprover]로 변환한다.
|
||||
ApprovalApprover toEntity() =>
|
||||
ApprovalApprover(id: id, employeeNo: employeeNo, name: name);
|
||||
}
|
||||
|
||||
/// 결재 단계 DTO.
|
||||
class ApprovalStepDto {
|
||||
ApprovalStepDto({
|
||||
this.id,
|
||||
@@ -206,6 +220,7 @@ class ApprovalStepDto {
|
||||
);
|
||||
}
|
||||
|
||||
/// DTO를 [ApprovalStep]으로 변환한다.
|
||||
ApprovalStep toEntity() => ApprovalStep(
|
||||
id: id,
|
||||
stepOrder: stepOrder,
|
||||
@@ -217,6 +232,7 @@ class ApprovalStepDto {
|
||||
);
|
||||
}
|
||||
|
||||
/// 결재 이력 DTO.
|
||||
class ApprovalHistoryDto {
|
||||
ApprovalHistoryDto({
|
||||
this.id,
|
||||
@@ -258,6 +274,7 @@ class ApprovalHistoryDto {
|
||||
);
|
||||
}
|
||||
|
||||
/// DTO를 [ApprovalHistory]로 변환한다.
|
||||
ApprovalHistory toEntity() => ApprovalHistory(
|
||||
id: id,
|
||||
action: action.toEntity(),
|
||||
@@ -269,6 +286,7 @@ class ApprovalHistoryDto {
|
||||
);
|
||||
}
|
||||
|
||||
/// 결재 행위(Action) DTO.
|
||||
class ApprovalActionDto {
|
||||
ApprovalActionDto({required this.id, required this.name});
|
||||
|
||||
@@ -282,9 +300,11 @@ class ApprovalActionDto {
|
||||
);
|
||||
}
|
||||
|
||||
/// DTO를 [ApprovalAction]으로 변환한다.
|
||||
ApprovalAction toEntity() => ApprovalAction(id: id, name: name);
|
||||
}
|
||||
|
||||
/// 문자열/DateTime 입력을 DateTime으로 변환한다.
|
||||
DateTime? _parseDate(Object? value) {
|
||||
if (value == null) return null;
|
||||
if (value is DateTime) return value;
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'package:superport_v2/core/common/utils/json_utils.dart';
|
||||
|
||||
import '../../domain/entities/approval_template.dart';
|
||||
|
||||
/// 결재 템플릿 API 응답을 표현하는 DTO.
|
||||
class ApprovalTemplateDto {
|
||||
ApprovalTemplateDto({
|
||||
required this.id,
|
||||
@@ -28,6 +29,7 @@ class ApprovalTemplateDto {
|
||||
final DateTime? updatedAt;
|
||||
final List<ApprovalTemplateStepDto> steps;
|
||||
|
||||
/// JSON을 [ApprovalTemplateDto]로 파싱한다.
|
||||
factory ApprovalTemplateDto.fromJson(Map<String, dynamic> json) {
|
||||
return ApprovalTemplateDto(
|
||||
id: json['id'] as int? ?? 0,
|
||||
@@ -50,6 +52,7 @@ class ApprovalTemplateDto {
|
||||
);
|
||||
}
|
||||
|
||||
/// DTO를 [ApprovalTemplate]으로 변환한다.
|
||||
ApprovalTemplate toEntity({bool includeSteps = true}) {
|
||||
return ApprovalTemplate(
|
||||
id: id,
|
||||
@@ -65,6 +68,7 @@ class ApprovalTemplateDto {
|
||||
);
|
||||
}
|
||||
|
||||
/// 페이징 응답을 파싱해 [PaginatedResult]를 반환한다.
|
||||
static PaginatedResult<ApprovalTemplate> parsePaginated(
|
||||
Map<String, dynamic>? json, {
|
||||
bool includeSteps = false,
|
||||
@@ -83,6 +87,7 @@ class ApprovalTemplateDto {
|
||||
}
|
||||
}
|
||||
|
||||
/// 템플릿 작성자 DTO.
|
||||
class ApprovalTemplateAuthorDto {
|
||||
ApprovalTemplateAuthorDto({
|
||||
required this.id,
|
||||
@@ -102,11 +107,13 @@ class ApprovalTemplateAuthorDto {
|
||||
);
|
||||
}
|
||||
|
||||
/// DTO를 [ApprovalTemplateAuthor]로 변환한다.
|
||||
ApprovalTemplateAuthor toEntity() {
|
||||
return ApprovalTemplateAuthor(id: id, employeeNo: employeeNo, name: name);
|
||||
}
|
||||
}
|
||||
|
||||
/// 템플릿 단계 DTO.
|
||||
class ApprovalTemplateStepDto {
|
||||
ApprovalTemplateStepDto({
|
||||
this.id,
|
||||
@@ -131,6 +138,7 @@ class ApprovalTemplateStepDto {
|
||||
);
|
||||
}
|
||||
|
||||
/// DTO를 [ApprovalTemplateStep]으로 변환한다.
|
||||
ApprovalTemplateStep toEntity() {
|
||||
return ApprovalTemplateStep(
|
||||
id: id,
|
||||
@@ -141,6 +149,7 @@ class ApprovalTemplateStepDto {
|
||||
}
|
||||
}
|
||||
|
||||
/// 템플릿 승인자 DTO.
|
||||
class ApprovalTemplateApproverDto {
|
||||
ApprovalTemplateApproverDto({
|
||||
required this.id,
|
||||
@@ -160,11 +169,13 @@ class ApprovalTemplateApproverDto {
|
||||
);
|
||||
}
|
||||
|
||||
/// DTO를 [ApprovalTemplateApprover]로 변환한다.
|
||||
ApprovalTemplateApprover toEntity() {
|
||||
return ApprovalTemplateApprover(id: id, employeeNo: employeeNo, name: name);
|
||||
}
|
||||
}
|
||||
|
||||
/// 문자열/DateTime을 파싱해 [DateTime]으로 반환한다.
|
||||
DateTime? _parseDate(Object? value) {
|
||||
if (value == null) return null;
|
||||
if (value is DateTime) return value;
|
||||
|
||||
@@ -6,6 +6,10 @@ import '../../domain/entities/approval.dart';
|
||||
import '../../domain/repositories/approval_repository.dart';
|
||||
import '../dtos/approval_dto.dart';
|
||||
|
||||
/// 결재 API 엔드포인트를 호출하는 원격 저장소 구현체.
|
||||
///
|
||||
/// - 모든 요청은 [ApiClient]를 통해 인증/에러 매핑을 공유한다.
|
||||
/// - 엔티티 변환은 DTO 계층에 위임한다.
|
||||
class ApprovalRepositoryRemote implements ApprovalRepository {
|
||||
ApprovalRepositoryRemote({required ApiClient apiClient}) : _api = apiClient;
|
||||
|
||||
@@ -13,6 +17,7 @@ class ApprovalRepositoryRemote implements ApprovalRepository {
|
||||
|
||||
static const _basePath = '/approvals';
|
||||
|
||||
/// 결재 목록을 조회한다. 필터 조건이 없으면 최신순 페이지를 반환한다.
|
||||
@override
|
||||
Future<PaginatedResult<Approval>> list({
|
||||
int page = 1,
|
||||
@@ -41,6 +46,7 @@ class ApprovalRepositoryRemote implements ApprovalRepository {
|
||||
return ApprovalDto.parsePaginated(response.data ?? const {});
|
||||
}
|
||||
|
||||
/// 결재 상세를 조회한다. 단계/이력 포함 여부를 쿼리 파라미터로 제어한다.
|
||||
@override
|
||||
Future<Approval> fetchDetail(
|
||||
int id, {
|
||||
@@ -59,6 +65,7 @@ class ApprovalRepositoryRemote implements ApprovalRepository {
|
||||
return ApprovalDto.fromJson(data).toEntity();
|
||||
}
|
||||
|
||||
/// 활성화된 결재 행위 목록을 조회한다.
|
||||
@override
|
||||
Future<List<ApprovalAction>> listActions({bool activeOnly = true}) async {
|
||||
final response = await _api.get<Map<String, dynamic>>(
|
||||
@@ -74,6 +81,7 @@ class ApprovalRepositoryRemote implements ApprovalRepository {
|
||||
return items;
|
||||
}
|
||||
|
||||
/// 결재 단계 행위를 수행하고 업데이트된 결재 정보를 반환한다.
|
||||
@override
|
||||
Future<Approval> performStepAction(ApprovalStepActionInput input) async {
|
||||
final response = await _api.post<Map<String, dynamic>>(
|
||||
@@ -90,6 +98,7 @@ class ApprovalRepositoryRemote implements ApprovalRepository {
|
||||
return ApprovalDto.fromJson(approvalJson).toEntity();
|
||||
}
|
||||
|
||||
/// 결재 단계들을 일괄로 생성하거나 재배치한다.
|
||||
@override
|
||||
Future<Approval> assignSteps(ApprovalStepAssignmentInput input) async {
|
||||
final response = await _api.post<Map<String, dynamic>>(
|
||||
@@ -106,6 +115,7 @@ class ApprovalRepositoryRemote implements ApprovalRepository {
|
||||
return ApprovalDto.fromJson(approvalJson).toEntity();
|
||||
}
|
||||
|
||||
/// 새로운 결재를 생성한다.
|
||||
@override
|
||||
Future<Approval> create(ApprovalInput input) async {
|
||||
final response = await _api.post<Map<String, dynamic>>(
|
||||
@@ -117,6 +127,7 @@ class ApprovalRepositoryRemote implements ApprovalRepository {
|
||||
return ApprovalDto.fromJson(data).toEntity();
|
||||
}
|
||||
|
||||
/// 결재 기본 정보를 수정한다.
|
||||
@override
|
||||
Future<Approval> update(int id, ApprovalInput input) async {
|
||||
final response = await _api.patch<Map<String, dynamic>>(
|
||||
@@ -128,11 +139,13 @@ class ApprovalRepositoryRemote implements ApprovalRepository {
|
||||
return ApprovalDto.fromJson(data).toEntity();
|
||||
}
|
||||
|
||||
/// 결재를 삭제(비활성화)한다.
|
||||
@override
|
||||
Future<void> delete(int id) async {
|
||||
await _api.delete<void>('$_basePath/$id');
|
||||
}
|
||||
|
||||
/// 삭제된 결재를 복구한다.
|
||||
@override
|
||||
Future<Approval> restore(int id) async {
|
||||
final response = await _api.post<Map<String, dynamic>>(
|
||||
@@ -143,6 +156,7 @@ class ApprovalRepositoryRemote implements ApprovalRepository {
|
||||
return ApprovalDto.fromJson(data).toEntity();
|
||||
}
|
||||
|
||||
/// 결재 단계/행위 응답에서 결재 객체 JSON을 추출한다.
|
||||
Map<String, dynamic>? _extractApprovalFromActionResponse(
|
||||
Map<String, dynamic> body,
|
||||
) {
|
||||
|
||||
@@ -6,6 +6,10 @@ import '../../domain/entities/approval_template.dart';
|
||||
import '../../domain/repositories/approval_template_repository.dart';
|
||||
import '../dtos/approval_template_dto.dart';
|
||||
|
||||
/// 결재 템플릿 관련 API를 호출하는 원격 저장소.
|
||||
///
|
||||
/// - 템플릿/단계 CRUD와 복구 API를 캡슐화한다.
|
||||
/// - 단계 등록은 별도 엔드포인트로 처리한다.
|
||||
class ApprovalTemplateRepositoryRemote implements ApprovalTemplateRepository {
|
||||
ApprovalTemplateRepositoryRemote({required ApiClient apiClient})
|
||||
: _api = apiClient;
|
||||
@@ -14,6 +18,7 @@ class ApprovalTemplateRepositoryRemote implements ApprovalTemplateRepository {
|
||||
|
||||
static const _basePath = '/approval-templates';
|
||||
|
||||
/// 결재 템플릿 목록을 조회한다. 검색/활성 여부 필터를 지원한다.
|
||||
@override
|
||||
Future<PaginatedResult<ApprovalTemplate>> list({
|
||||
int page = 1,
|
||||
@@ -34,6 +39,7 @@ class ApprovalTemplateRepositoryRemote implements ApprovalTemplateRepository {
|
||||
return ApprovalTemplateDto.parsePaginated(response.data);
|
||||
}
|
||||
|
||||
/// 템플릿 상세 정보를 조회한다. 필요 시 단계 포함 여부를 지정한다.
|
||||
@override
|
||||
Future<ApprovalTemplate> fetchDetail(
|
||||
int id, {
|
||||
@@ -50,6 +56,7 @@ class ApprovalTemplateRepositoryRemote implements ApprovalTemplateRepository {
|
||||
).toEntity(includeSteps: includeSteps);
|
||||
}
|
||||
|
||||
/// 템플릿을 생성하고 필요하면 단계까지 함께 등록한다.
|
||||
@override
|
||||
Future<ApprovalTemplate> create(
|
||||
ApprovalTemplateInput input, {
|
||||
@@ -70,6 +77,7 @@ class ApprovalTemplateRepositoryRemote implements ApprovalTemplateRepository {
|
||||
return fetchDetail(created.id, includeSteps: true);
|
||||
}
|
||||
|
||||
/// 템플릿 기본 정보와 단계 구성을 수정한다.
|
||||
@override
|
||||
Future<ApprovalTemplate> update(
|
||||
int id,
|
||||
@@ -87,11 +95,13 @@ class ApprovalTemplateRepositoryRemote implements ApprovalTemplateRepository {
|
||||
return fetchDetail(id, includeSteps: true);
|
||||
}
|
||||
|
||||
/// 템플릿을 삭제한다.
|
||||
@override
|
||||
Future<void> delete(int id) async {
|
||||
await _api.delete<void>('$_basePath/$id');
|
||||
}
|
||||
|
||||
/// 삭제된 템플릿을 복구한다.
|
||||
@override
|
||||
Future<ApprovalTemplate> restore(int id) async {
|
||||
final response = await _api.post<Map<String, dynamic>>(
|
||||
@@ -102,6 +112,7 @@ class ApprovalTemplateRepositoryRemote implements ApprovalTemplateRepository {
|
||||
return ApprovalTemplateDto.fromJson(data).toEntity(includeSteps: false);
|
||||
}
|
||||
|
||||
/// 템플릿 단계 전체를 신규로 등록한다.
|
||||
Future<void> _postSteps(
|
||||
int templateId,
|
||||
List<ApprovalTemplateStepInput> steps,
|
||||
@@ -117,6 +128,7 @@ class ApprovalTemplateRepositoryRemote implements ApprovalTemplateRepository {
|
||||
);
|
||||
}
|
||||
|
||||
/// 템플릿 단계 정보를 부분 수정한다.
|
||||
Future<void> _patchSteps(
|
||||
int templateId,
|
||||
List<ApprovalTemplateStepInput> steps,
|
||||
|
||||
@@ -2,7 +2,11 @@ import 'package:superport_v2/core/common/models/paginated_result.dart';
|
||||
|
||||
import '../entities/approval.dart';
|
||||
|
||||
/// 결재 도메인에서 사용하는 저장소 인터페이스.
|
||||
///
|
||||
/// - presentation 레이어는 이 인터페이스만 의존하며, 실제 구현은 data 레이어가 담당한다.
|
||||
abstract class ApprovalRepository {
|
||||
/// 결재 목록을 조회한다. 필터/페이지 조건을 지원한다.
|
||||
Future<PaginatedResult<Approval>> list({
|
||||
int page = 1,
|
||||
int pageSize = 20,
|
||||
@@ -14,6 +18,7 @@ abstract class ApprovalRepository {
|
||||
bool includeSteps = false,
|
||||
});
|
||||
|
||||
/// 결재 상세 정보를 조회한다.
|
||||
Future<Approval> fetchDetail(
|
||||
int id, {
|
||||
bool includeSteps = true,
|
||||
@@ -29,11 +34,15 @@ abstract class ApprovalRepository {
|
||||
/// 결재 단계 일괄 생성/재배치
|
||||
Future<Approval> assignSteps(ApprovalStepAssignmentInput input);
|
||||
|
||||
/// 결재를 생성한다.
|
||||
Future<Approval> create(ApprovalInput input);
|
||||
|
||||
/// 결재를 수정한다.
|
||||
Future<Approval> update(int id, ApprovalInput input);
|
||||
|
||||
/// 결재를 삭제한다.
|
||||
Future<void> delete(int id);
|
||||
|
||||
/// 삭제된 결재를 복구한다.
|
||||
Future<Approval> restore(int id);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,9 @@ import 'package:superport_v2/core/common/models/paginated_result.dart';
|
||||
|
||||
import '../entities/approval_template.dart';
|
||||
|
||||
/// 결재 템플릿 도메인 저장소 인터페이스.
|
||||
abstract class ApprovalTemplateRepository {
|
||||
/// 템플릿 목록을 조회한다.
|
||||
Future<PaginatedResult<ApprovalTemplate>> list({
|
||||
int page = 1,
|
||||
int pageSize = 20,
|
||||
@@ -10,20 +12,25 @@ abstract class ApprovalTemplateRepository {
|
||||
bool? isActive,
|
||||
});
|
||||
|
||||
/// 템플릿 상세를 조회한다.
|
||||
Future<ApprovalTemplate> fetchDetail(int id, {bool includeSteps = true});
|
||||
|
||||
/// 템플릿을 생성한다. 단계 입력은 옵션이다.
|
||||
Future<ApprovalTemplate> create(
|
||||
ApprovalTemplateInput input, {
|
||||
List<ApprovalTemplateStepInput> steps = const [],
|
||||
});
|
||||
|
||||
/// 템플릿 기본 정보와 단계 구성을 수정한다.
|
||||
Future<ApprovalTemplate> update(
|
||||
int id,
|
||||
ApprovalTemplateInput input, {
|
||||
List<ApprovalTemplateStepInput>? steps,
|
||||
});
|
||||
|
||||
/// 템플릿을 삭제한다.
|
||||
Future<void> delete(int id);
|
||||
|
||||
/// 삭제된 템플릿을 복구한다.
|
||||
Future<ApprovalTemplate> restore(int id);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import 'package:superport_v2/features/approvals/domain/entities/approval.dart';
|
||||
|
||||
import '../../domain/entities/approval_history_record.dart';
|
||||
|
||||
/// 결재 이력(History) API 응답을 표현하는 DTO.
|
||||
class ApprovalHistoryRecordDto {
|
||||
ApprovalHistoryRecordDto({
|
||||
required this.id,
|
||||
@@ -30,6 +31,7 @@ class ApprovalHistoryRecordDto {
|
||||
final DateTime actionAt;
|
||||
final String? note;
|
||||
|
||||
/// 원본 JSON에서 필드를 파싱해 DTO를 생성한다.
|
||||
factory ApprovalHistoryRecordDto.fromJson(Map<String, dynamic> json) {
|
||||
final approvalData = json['approval'] as Map<String, dynamic>?;
|
||||
final id = json['id'] as int? ?? 0;
|
||||
@@ -74,6 +76,7 @@ class ApprovalHistoryRecordDto {
|
||||
);
|
||||
}
|
||||
|
||||
/// DTO를 도메인 [ApprovalHistoryRecord] 엔티티로 변환한다.
|
||||
ApprovalHistoryRecord toEntity() {
|
||||
return ApprovalHistoryRecord(
|
||||
id: id,
|
||||
@@ -89,6 +92,7 @@ class ApprovalHistoryRecordDto {
|
||||
);
|
||||
}
|
||||
|
||||
/// 페이징 응답을 읽어 [PaginatedResult] 형태로 변환한다.
|
||||
static PaginatedResult<ApprovalHistoryRecord> parsePaginated(
|
||||
Map<String, dynamic>? json,
|
||||
) {
|
||||
@@ -107,6 +111,7 @@ class ApprovalHistoryRecordDto {
|
||||
}
|
||||
}
|
||||
|
||||
/// 다양한 형식으로 전달될 수 있는 날짜 값을 파싱한다.
|
||||
DateTime? _parseDate(Object? value) {
|
||||
if (value == null) return null;
|
||||
if (value is DateTime) return value;
|
||||
|
||||
@@ -6,6 +6,7 @@ import '../../domain/entities/approval_history_record.dart';
|
||||
import '../../domain/repositories/approval_history_repository.dart';
|
||||
import '../dtos/approval_history_record_dto.dart';
|
||||
|
||||
/// 결재 이력 API를 호출하는 원격 저장소 구현체.
|
||||
class ApprovalHistoryRepositoryRemote implements ApprovalHistoryRepository {
|
||||
ApprovalHistoryRepositoryRemote({required ApiClient apiClient})
|
||||
: _api = apiClient;
|
||||
@@ -14,6 +15,7 @@ class ApprovalHistoryRepositoryRemote implements ApprovalHistoryRepository {
|
||||
|
||||
static const _basePath = '/approval-histories';
|
||||
|
||||
/// 결재 이력 목록을 조회한다.
|
||||
@override
|
||||
Future<PaginatedResult<ApprovalHistoryRecord>> list({
|
||||
int page = 1,
|
||||
|
||||
@@ -2,7 +2,9 @@ import 'package:superport_v2/core/common/models/paginated_result.dart';
|
||||
|
||||
import '../entities/approval_history_record.dart';
|
||||
|
||||
/// 결재 이력 데이터를 조회하는 도메인 저장소 인터페이스.
|
||||
abstract class ApprovalHistoryRepository {
|
||||
/// 이력 목록을 조회한다.
|
||||
Future<PaginatedResult<ApprovalHistoryRecord>> list({
|
||||
int page = 1,
|
||||
int pageSize = 20,
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'package:flutter/widgets.dart';
|
||||
|
||||
import '../../../presentation/pages/approval_page.dart';
|
||||
|
||||
/// 결재 요청 탭에서 사용하는 래퍼 페이지. 실 구현은 [ApprovalPage]를 재사용한다.
|
||||
class ApprovalRequestPage extends StatelessWidget {
|
||||
const ApprovalRequestPage({super.key});
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import 'package:superport_v2/features/approvals/domain/entities/approval.dart';
|
||||
|
||||
import '../../domain/entities/approval_step_record.dart';
|
||||
|
||||
/// 결재 단계 기록 API 응답을 표현하는 DTO.
|
||||
class ApprovalStepRecordDto {
|
||||
ApprovalStepRecordDto({
|
||||
required this.approvalId,
|
||||
@@ -20,6 +21,7 @@ class ApprovalStepRecordDto {
|
||||
final String? templateName;
|
||||
final ApprovalStep step;
|
||||
|
||||
/// JSON에서 필요한 필드를 추출해 DTO를 생성한다.
|
||||
factory ApprovalStepRecordDto.fromJson(Map<String, dynamic> json) {
|
||||
final approvalData = json['approval'] as Map<String, dynamic>?;
|
||||
final approvalId =
|
||||
@@ -49,6 +51,7 @@ class ApprovalStepRecordDto {
|
||||
);
|
||||
}
|
||||
|
||||
/// DTO를 [ApprovalStepRecord] 엔티티로 변환한다.
|
||||
ApprovalStepRecord toEntity() {
|
||||
return ApprovalStepRecord(
|
||||
approvalId: approvalId,
|
||||
@@ -59,6 +62,7 @@ class ApprovalStepRecordDto {
|
||||
);
|
||||
}
|
||||
|
||||
/// 페이징 응답을 [PaginatedResult] 형태로 반환한다.
|
||||
static PaginatedResult<ApprovalStepRecord> parsePaginated(
|
||||
Map<String, dynamic>? json,
|
||||
) {
|
||||
|
||||
@@ -7,6 +7,7 @@ import 'package:superport_v2/features/approvals/step/domain/repositories/approva
|
||||
import '../dtos/approval_step_record_dto.dart';
|
||||
import '../../domain/entities/approval_step_input.dart';
|
||||
|
||||
/// 결재 단계 API를 호출하는 원격 저장소 구현체.
|
||||
class ApprovalStepRepositoryRemote implements ApprovalStepRepository {
|
||||
ApprovalStepRepositoryRemote({required ApiClient apiClient})
|
||||
: _api = apiClient;
|
||||
@@ -15,6 +16,7 @@ class ApprovalStepRepositoryRemote implements ApprovalStepRepository {
|
||||
|
||||
static const _basePath = '/approval-steps';
|
||||
|
||||
/// 결재 단계 목록을 조회한다.
|
||||
@override
|
||||
Future<PaginatedResult<ApprovalStepRecord>> list({
|
||||
int page = 1,
|
||||
@@ -40,6 +42,7 @@ class ApprovalStepRepositoryRemote implements ApprovalStepRepository {
|
||||
return ApprovalStepRecordDto.parsePaginated(response.data);
|
||||
}
|
||||
|
||||
/// 단일 결재 단계 상세를 조회한다.
|
||||
@override
|
||||
Future<ApprovalStepRecord> fetchDetail(int id) async {
|
||||
final response = await _api.get<Map<String, dynamic>>(
|
||||
@@ -50,6 +53,7 @@ class ApprovalStepRepositoryRemote implements ApprovalStepRepository {
|
||||
return ApprovalStepRecordDto.fromJson(data).toEntity();
|
||||
}
|
||||
|
||||
/// 결재 단계를 생성한다.
|
||||
@override
|
||||
Future<ApprovalStepRecord> create(ApprovalStepInput input) async {
|
||||
final response = await _api.post<Map<String, dynamic>>(
|
||||
@@ -64,6 +68,7 @@ class ApprovalStepRepositoryRemote implements ApprovalStepRepository {
|
||||
return ApprovalStepRecordDto.fromJson(data).toEntity();
|
||||
}
|
||||
|
||||
/// 결재 단계를 수정한다.
|
||||
@override
|
||||
Future<ApprovalStepRecord> update(int id, ApprovalStepInput input) async {
|
||||
final response = await _api.patch<Map<String, dynamic>>(
|
||||
|
||||
@@ -3,7 +3,9 @@ import 'package:superport_v2/core/common/models/paginated_result.dart';
|
||||
import '../entities/approval_step_input.dart';
|
||||
import '../entities/approval_step_record.dart';
|
||||
|
||||
/// 결재 단계 목록/상세를 다루는 도메인 저장소 인터페이스.
|
||||
abstract class ApprovalStepRepository {
|
||||
/// 결재 단계 목록을 조회한다.
|
||||
Future<PaginatedResult<ApprovalStepRecord>> list({
|
||||
int page = 1,
|
||||
int pageSize = 20,
|
||||
@@ -13,6 +15,7 @@ abstract class ApprovalStepRepository {
|
||||
int? approvalId,
|
||||
});
|
||||
|
||||
/// 결재 단계 상세를 조회한다.
|
||||
Future<ApprovalStepRecord> fetchDetail(int id);
|
||||
|
||||
/// 결재 단계를 생성한다.
|
||||
|
||||
@@ -14,6 +14,7 @@ import '../../domain/entities/approval_step_input.dart';
|
||||
import '../../domain/entities/approval_step_record.dart';
|
||||
import '../../domain/repositories/approval_step_repository.dart';
|
||||
|
||||
/// 결재 단계 관리 진입 페이지. 기능 플래그에 따라 실제 화면 또는 준비중 화면을 노출한다.
|
||||
class ApprovalStepPage extends StatelessWidget {
|
||||
const ApprovalStepPage({super.key});
|
||||
|
||||
@@ -50,6 +51,7 @@ class ApprovalStepPage extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
/// 결재 단계 기능이 활성화된 경우 사용하는 실제 화면 위젯.
|
||||
class _ApprovalStepEnabledPage extends StatefulWidget {
|
||||
const _ApprovalStepEnabledPage();
|
||||
|
||||
@@ -58,6 +60,7 @@ class _ApprovalStepEnabledPage extends StatefulWidget {
|
||||
_ApprovalStepEnabledPageState();
|
||||
}
|
||||
|
||||
/// 결재 단계 목록과 필터 상태를 관리하는 상태 클래스.
|
||||
class _ApprovalStepEnabledPageState extends State<_ApprovalStepEnabledPage> {
|
||||
late final ApprovalStepController _controller;
|
||||
final TextEditingController _searchController = TextEditingController();
|
||||
|
||||
@@ -15,6 +15,7 @@ import '../../../domain/entities/approval_template.dart';
|
||||
import '../../../domain/repositories/approval_template_repository.dart';
|
||||
import '../controllers/approval_template_controller.dart';
|
||||
|
||||
/// 결재 템플릿 관리 페이지. 기능 플래그에 따라 준비중 화면을 노출한다.
|
||||
class ApprovalTemplatePage extends StatelessWidget {
|
||||
const ApprovalTemplatePage({super.key});
|
||||
|
||||
@@ -51,6 +52,7 @@ class ApprovalTemplatePage extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
/// 결재 템플릿 기능이 활성화된 경우 사용하는 실제 화면 위젯.
|
||||
class _ApprovalTemplateEnabledPage extends StatefulWidget {
|
||||
const _ApprovalTemplateEnabledPage();
|
||||
|
||||
@@ -59,6 +61,7 @@ class _ApprovalTemplateEnabledPage extends StatefulWidget {
|
||||
_ApprovalTemplateEnabledPageState();
|
||||
}
|
||||
|
||||
/// 템플릿 목록/필터/폼 상태를 관리하는 상태 클래스.
|
||||
class _ApprovalTemplateEnabledPageState
|
||||
extends State<_ApprovalTemplateEnabledPage> {
|
||||
late final ApprovalTemplateController _controller;
|
||||
|
||||
Reference in New Issue
Block a user