feat(approvals): Approval Flow v2 프런트엔드 전면 개편
- 환경/라우터 모듈에 approval_flow_v2 토글을 추가하고 FeatureFlags 초기화를 연결 (.env*, lib/core/**) - ApiClient 빌더·ApiRoutes 확장과 ApprovalRepositoryRemote 리팩터링으로 include·액션 시그니처를 정합화 - ApprovalFlow·ApprovalDraft 엔티티/레포/유즈케이스를 도입해 서버 초안과 단계 액션(승인·회수·재상신)을 지원 - Approval 컨트롤러·히스토리·템플릿 페이지와 공유 위젯을 재작성해 감사 로그·회수 UX·템플릿 CRUD를 반영 - Inbound/Outbound/Rental 컨트롤러·페이지에 결재 섹션을 삽입하고 대시보드 pending 카드 요약을 갱신 - SuperportDialog·FormField 등 공통 위젯을 보강하고 승인 위젯 가이드를 추가해 UI 가이드를 정리 - 결재/재고 테스트 픽스처와 단위·위젯·통합 테스트를 확장하고 flutter_test_config로 스테이징 호스트를 허용 - Approval Flow 레포트/플랜 문서를 업데이트하고 ApprovalFlow_System_Integration_and_ChangePlan.md를 추가 - 실행: flutter analyze, flutter test
This commit is contained in:
@@ -7,6 +7,27 @@ import 'core/network/api_client.dart';
|
||||
import 'core/network/api_error.dart';
|
||||
import 'core/network/interceptors/auth_interceptor.dart';
|
||||
import 'core/services/token_storage.dart';
|
||||
import 'features/approvals/data/repositories/approval_draft_repository_remote.dart';
|
||||
import 'features/approvals/data/repositories/approval_repository_remote.dart';
|
||||
import 'features/approvals/data/repositories/approval_template_repository_remote.dart';
|
||||
import 'features/approvals/domain/repositories/approval_draft_repository.dart';
|
||||
import 'features/approvals/domain/repositories/approval_repository.dart';
|
||||
import 'features/approvals/domain/repositories/approval_template_repository.dart';
|
||||
import 'features/approvals/domain/usecases/apply_approval_template_use_case.dart';
|
||||
import 'features/approvals/domain/usecases/approve_approval_use_case.dart';
|
||||
import 'features/approvals/domain/usecases/delete_approval_draft_use_case.dart';
|
||||
import 'features/approvals/domain/usecases/get_approval_draft_use_case.dart';
|
||||
import 'features/approvals/domain/usecases/list_approval_drafts_use_case.dart';
|
||||
import 'features/approvals/domain/usecases/recall_approval_use_case.dart';
|
||||
import 'features/approvals/domain/usecases/reject_approval_use_case.dart';
|
||||
import 'features/approvals/domain/usecases/resubmit_approval_use_case.dart';
|
||||
import 'features/approvals/domain/usecases/save_approval_draft_use_case.dart';
|
||||
import 'features/approvals/domain/usecases/save_approval_template_use_case.dart';
|
||||
import 'features/approvals/domain/usecases/submit_approval_use_case.dart';
|
||||
import 'features/approvals/history/data/repositories/approval_history_repository_remote.dart';
|
||||
import 'features/approvals/history/domain/repositories/approval_history_repository.dart';
|
||||
import 'features/approvals/step/data/repositories/approval_step_repository_remote.dart';
|
||||
import 'features/approvals/step/domain/repositories/approval_step_repository.dart';
|
||||
import 'features/auth/application/auth_service.dart';
|
||||
import 'features/auth/data/repositories/auth_repository_remote.dart';
|
||||
import 'features/auth/domain/repositories/auth_repository.dart';
|
||||
@@ -22,32 +43,24 @@ import 'features/masters/customer/data/repositories/customer_repository_remote.d
|
||||
import 'features/masters/customer/domain/repositories/customer_repository.dart';
|
||||
import 'features/masters/group/data/repositories/group_repository_remote.dart';
|
||||
import 'features/masters/group/domain/repositories/group_repository.dart';
|
||||
import 'features/masters/menu/data/repositories/menu_repository_remote.dart';
|
||||
import 'features/masters/menu/domain/repositories/menu_repository.dart';
|
||||
import 'features/masters/group_permission/data/repositories/group_permission_repository_remote.dart';
|
||||
import 'features/masters/group_permission/domain/repositories/group_permission_repository.dart';
|
||||
import 'features/masters/menu/data/repositories/menu_repository_remote.dart';
|
||||
import 'features/masters/menu/domain/repositories/menu_repository.dart';
|
||||
import 'features/masters/product/data/repositories/product_repository_remote.dart';
|
||||
import 'features/masters/product/domain/repositories/product_repository.dart';
|
||||
import 'features/masters/uom/data/repositories/uom_repository_remote.dart';
|
||||
import 'features/masters/uom/domain/repositories/uom_repository.dart';
|
||||
import 'features/masters/user/data/repositories/user_repository_remote.dart';
|
||||
import 'features/masters/user/domain/repositories/user_repository.dart';
|
||||
import 'features/masters/vendor/data/repositories/vendor_repository_remote.dart';
|
||||
import 'features/masters/vendor/domain/repositories/vendor_repository.dart';
|
||||
import 'features/masters/warehouse/data/repositories/warehouse_repository_remote.dart';
|
||||
import 'features/masters/warehouse/domain/repositories/warehouse_repository.dart';
|
||||
import 'features/masters/uom/data/repositories/uom_repository_remote.dart';
|
||||
import 'features/masters/uom/domain/repositories/uom_repository.dart';
|
||||
import 'features/approvals/data/repositories/approval_repository_remote.dart';
|
||||
import 'features/approvals/data/repositories/approval_template_repository_remote.dart';
|
||||
import 'features/approvals/history/data/repositories/approval_history_repository_remote.dart';
|
||||
import 'features/approvals/history/domain/repositories/approval_history_repository.dart';
|
||||
import 'features/approvals/step/data/repositories/approval_step_repository_remote.dart';
|
||||
import 'features/approvals/domain/repositories/approval_repository.dart';
|
||||
import 'features/approvals/domain/repositories/approval_template_repository.dart';
|
||||
import 'features/approvals/step/domain/repositories/approval_step_repository.dart';
|
||||
import 'features/util/postal_search/data/repositories/postal_search_repository_remote.dart';
|
||||
import 'features/util/postal_search/domain/repositories/postal_search_repository.dart';
|
||||
import 'features/reporting/data/repositories/reporting_repository_remote.dart';
|
||||
import 'features/reporting/domain/repositories/reporting_repository.dart';
|
||||
import 'features/util/postal_search/data/repositories/postal_search_repository_remote.dart';
|
||||
import 'features/util/postal_search/domain/repositories/postal_search_repository.dart';
|
||||
|
||||
/// 전역 DI 컨테이너
|
||||
final GetIt sl = GetIt.instance;
|
||||
@@ -69,10 +82,12 @@ Future<void> initInjection({
|
||||
|
||||
final dio = Dio(options);
|
||||
|
||||
// 인터셉터 등록 (Auth 등)
|
||||
final tokenStorage = createTokenStorage();
|
||||
sl.registerLazySingleton<TokenStorage>(() => tokenStorage);
|
||||
sl.registerLazySingleton<ApiErrorMapper>(ApiErrorMapper.new);
|
||||
sl
|
||||
..registerSingleton<TokenStorage>(tokenStorage)
|
||||
..registerLazySingleton<ApiErrorMapper>(ApiErrorMapper.new);
|
||||
|
||||
// 인터셉터 등록 (Auth 등)
|
||||
|
||||
final authInterceptor = AuthInterceptor(
|
||||
tokenStorage: tokenStorage,
|
||||
@@ -89,99 +104,154 @@ Future<void> initInjection({
|
||||
// 개발용 로거는 필요 시 추가 (pretty_dio_logger 등)
|
||||
// if (!kReleaseMode) { dio.interceptors.add(PrettyDioLogger(...)); }
|
||||
|
||||
sl.registerSingleton<Dio>(dio);
|
||||
|
||||
// ApiClient 등록
|
||||
sl.registerLazySingleton<ApiClient>(
|
||||
() => ApiClient(dio: dio, errorMapper: sl<ApiErrorMapper>()),
|
||||
() => ApiClient(dio: sl<Dio>(), errorMapper: sl<ApiErrorMapper>()),
|
||||
);
|
||||
|
||||
// 인증 서비스 등록
|
||||
sl.registerLazySingleton<AuthRepository>(
|
||||
() => AuthRepositoryRemote(apiClient: sl<ApiClient>()),
|
||||
);
|
||||
sl.registerLazySingleton<AuthService>(
|
||||
() => AuthService(
|
||||
repository: sl<AuthRepository>(),
|
||||
tokenStorage: sl<TokenStorage>(),
|
||||
),
|
||||
);
|
||||
_registerAuthDependencies();
|
||||
_registerDashboardDependencies();
|
||||
_registerMasterDependencies();
|
||||
_registerApprovalDependencies();
|
||||
_registerInventoryDependencies();
|
||||
_registerUtilityDependencies();
|
||||
_registerReportingDependencies();
|
||||
}
|
||||
|
||||
void _registerAuthDependencies() {
|
||||
sl
|
||||
..registerLazySingleton<AuthRepository>(
|
||||
() => AuthRepositoryRemote(apiClient: sl<ApiClient>()),
|
||||
)
|
||||
..registerLazySingleton<AuthService>(
|
||||
() => AuthService(
|
||||
repository: sl<AuthRepository>(),
|
||||
tokenStorage: sl<TokenStorage>(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _registerDashboardDependencies() {
|
||||
sl.registerLazySingleton<DashboardRepository>(
|
||||
() => DashboardRepositoryRemote(apiClient: sl<ApiClient>()),
|
||||
);
|
||||
}
|
||||
|
||||
// 리포지토리 등록 (예: 벤더)
|
||||
sl.registerLazySingleton<VendorRepository>(
|
||||
() => VendorRepositoryRemote(apiClient: sl<ApiClient>()),
|
||||
);
|
||||
void _registerMasterDependencies() {
|
||||
sl
|
||||
..registerLazySingleton<VendorRepository>(
|
||||
() => VendorRepositoryRemote(apiClient: sl<ApiClient>()),
|
||||
)
|
||||
..registerLazySingleton<ProductRepository>(
|
||||
() => ProductRepositoryRemote(apiClient: sl<ApiClient>()),
|
||||
)
|
||||
..registerLazySingleton<WarehouseRepository>(
|
||||
() => WarehouseRepositoryRemote(apiClient: sl<ApiClient>()),
|
||||
)
|
||||
..registerLazySingleton<UomRepository>(
|
||||
() => UomRepositoryRemote(apiClient: sl<ApiClient>()),
|
||||
)
|
||||
..registerLazySingleton<CustomerRepository>(
|
||||
() => CustomerRepositoryRemote(apiClient: sl<ApiClient>()),
|
||||
)
|
||||
..registerLazySingleton<GroupRepository>(
|
||||
() => GroupRepositoryRemote(apiClient: sl<ApiClient>()),
|
||||
)
|
||||
..registerLazySingleton<UserRepository>(
|
||||
() => UserRepositoryRemote(apiClient: sl<ApiClient>()),
|
||||
)
|
||||
..registerLazySingleton<MenuRepository>(
|
||||
() => MenuRepositoryRemote(apiClient: sl<ApiClient>()),
|
||||
)
|
||||
..registerLazySingleton<GroupPermissionRepository>(
|
||||
() => GroupPermissionRepositoryRemote(apiClient: sl<ApiClient>()),
|
||||
);
|
||||
}
|
||||
|
||||
sl.registerLazySingleton<ProductRepository>(
|
||||
() => ProductRepositoryRemote(apiClient: sl<ApiClient>()),
|
||||
);
|
||||
void _registerApprovalDependencies() {
|
||||
sl
|
||||
..registerLazySingleton<ApprovalRepository>(
|
||||
() => ApprovalRepositoryRemote(apiClient: sl<ApiClient>()),
|
||||
)
|
||||
..registerLazySingleton<ApprovalTemplateRepository>(
|
||||
() => ApprovalTemplateRepositoryRemote(apiClient: sl<ApiClient>()),
|
||||
)
|
||||
..registerLazySingleton<ApprovalStepRepository>(
|
||||
() => ApprovalStepRepositoryRemote(apiClient: sl<ApiClient>()),
|
||||
)
|
||||
..registerLazySingleton<ApprovalHistoryRepository>(
|
||||
() => ApprovalHistoryRepositoryRemote(apiClient: sl<ApiClient>()),
|
||||
)
|
||||
..registerLazySingleton<ApprovalDraftRepository>(
|
||||
() => ApprovalDraftRepositoryRemote(apiClient: sl<ApiClient>()),
|
||||
)
|
||||
..registerLazySingleton<SubmitApprovalUseCase>(
|
||||
() => SubmitApprovalUseCase(repository: sl<ApprovalRepository>()),
|
||||
)
|
||||
..registerLazySingleton<ApproveApprovalUseCase>(
|
||||
() => ApproveApprovalUseCase(repository: sl<ApprovalRepository>()),
|
||||
)
|
||||
..registerLazySingleton<RejectApprovalUseCase>(
|
||||
() => RejectApprovalUseCase(repository: sl<ApprovalRepository>()),
|
||||
)
|
||||
..registerLazySingleton<RecallApprovalUseCase>(
|
||||
() => RecallApprovalUseCase(repository: sl<ApprovalRepository>()),
|
||||
)
|
||||
..registerLazySingleton<ResubmitApprovalUseCase>(
|
||||
() => ResubmitApprovalUseCase(repository: sl<ApprovalRepository>()),
|
||||
)
|
||||
..registerLazySingleton<SaveApprovalTemplateUseCase>(
|
||||
() => SaveApprovalTemplateUseCase(
|
||||
repository: sl<ApprovalTemplateRepository>(),
|
||||
),
|
||||
)
|
||||
..registerLazySingleton<SaveApprovalDraftUseCase>(
|
||||
() => SaveApprovalDraftUseCase(repository: sl<ApprovalDraftRepository>()),
|
||||
)
|
||||
..registerLazySingleton<GetApprovalDraftUseCase>(
|
||||
() => GetApprovalDraftUseCase(repository: sl<ApprovalDraftRepository>()),
|
||||
)
|
||||
..registerLazySingleton<ListApprovalDraftsUseCase>(
|
||||
() =>
|
||||
ListApprovalDraftsUseCase(repository: sl<ApprovalDraftRepository>()),
|
||||
)
|
||||
..registerLazySingleton<DeleteApprovalDraftUseCase>(
|
||||
() =>
|
||||
DeleteApprovalDraftUseCase(repository: sl<ApprovalDraftRepository>()),
|
||||
)
|
||||
..registerLazySingleton<ApplyApprovalTemplateUseCase>(
|
||||
() => ApplyApprovalTemplateUseCase(
|
||||
templateRepository: sl<ApprovalTemplateRepository>(),
|
||||
approvalRepository: sl<ApprovalRepository>(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
sl.registerLazySingleton<WarehouseRepository>(
|
||||
() => WarehouseRepositoryRemote(apiClient: sl<ApiClient>()),
|
||||
);
|
||||
|
||||
sl.registerLazySingleton<UomRepository>(
|
||||
() => UomRepositoryRemote(apiClient: sl<ApiClient>()),
|
||||
);
|
||||
|
||||
sl.registerLazySingleton<CustomerRepository>(
|
||||
() => CustomerRepositoryRemote(apiClient: sl<ApiClient>()),
|
||||
);
|
||||
|
||||
sl.registerLazySingleton<GroupRepository>(
|
||||
() => GroupRepositoryRemote(apiClient: sl<ApiClient>()),
|
||||
);
|
||||
|
||||
sl.registerLazySingleton<UserRepository>(
|
||||
() => UserRepositoryRemote(apiClient: sl<ApiClient>()),
|
||||
);
|
||||
|
||||
sl.registerLazySingleton<MenuRepository>(
|
||||
() => MenuRepositoryRemote(apiClient: sl<ApiClient>()),
|
||||
);
|
||||
|
||||
sl.registerLazySingleton<GroupPermissionRepository>(
|
||||
() => GroupPermissionRepositoryRemote(apiClient: sl<ApiClient>()),
|
||||
);
|
||||
|
||||
sl.registerLazySingleton<ApprovalRepository>(
|
||||
() => ApprovalRepositoryRemote(apiClient: sl<ApiClient>()),
|
||||
);
|
||||
|
||||
sl.registerLazySingleton<ApprovalTemplateRepository>(
|
||||
() => ApprovalTemplateRepositoryRemote(apiClient: sl<ApiClient>()),
|
||||
);
|
||||
|
||||
sl.registerLazySingleton<ApprovalStepRepository>(
|
||||
() => ApprovalStepRepositoryRemote(apiClient: sl<ApiClient>()),
|
||||
);
|
||||
|
||||
sl.registerLazySingleton<ApprovalHistoryRepository>(
|
||||
() => ApprovalHistoryRepositoryRemote(apiClient: sl<ApiClient>()),
|
||||
);
|
||||
void _registerInventoryDependencies() {
|
||||
sl
|
||||
..registerLazySingleton<InventoryLookupRepository>(
|
||||
() => InventoryLookupRepositoryRemote(apiClient: sl<ApiClient>()),
|
||||
)
|
||||
..registerLazySingleton<StockTransactionRepository>(
|
||||
() => StockTransactionRepositoryRemote(apiClient: sl<ApiClient>()),
|
||||
)
|
||||
..registerLazySingleton<TransactionLineRepository>(
|
||||
() => TransactionLineRepositoryRemote(apiClient: sl<ApiClient>()),
|
||||
)
|
||||
..registerLazySingleton<TransactionCustomerRepository>(
|
||||
() => TransactionCustomerRepositoryRemote(apiClient: sl<ApiClient>()),
|
||||
);
|
||||
}
|
||||
|
||||
void _registerUtilityDependencies() {
|
||||
sl.registerLazySingleton<PostalSearchRepository>(
|
||||
() => PostalSearchRepositoryRemote(apiClient: sl<ApiClient>()),
|
||||
);
|
||||
}
|
||||
|
||||
sl.registerLazySingleton<InventoryLookupRepository>(
|
||||
() => InventoryLookupRepositoryRemote(apiClient: sl<ApiClient>()),
|
||||
);
|
||||
|
||||
sl.registerLazySingleton<StockTransactionRepository>(
|
||||
() => StockTransactionRepositoryRemote(apiClient: sl<ApiClient>()),
|
||||
);
|
||||
|
||||
sl.registerLazySingleton<TransactionLineRepository>(
|
||||
() => TransactionLineRepositoryRemote(apiClient: sl<ApiClient>()),
|
||||
);
|
||||
|
||||
sl.registerLazySingleton<TransactionCustomerRepository>(
|
||||
() => TransactionCustomerRepositoryRemote(apiClient: sl<ApiClient>()),
|
||||
);
|
||||
|
||||
void _registerReportingDependencies() {
|
||||
sl.registerLazySingleton<ReportingRepository>(
|
||||
() => ReportingRepositoryRemote(apiClient: sl<ApiClient>()),
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user