feat: 결재·마스터 실연동 업데이트

This commit is contained in:
JiWoong Sul
2025-10-14 18:10:24 +09:00
parent 1325109fba
commit 8067416c09
66 changed files with 2129 additions and 222 deletions

View File

@@ -7,6 +7,7 @@ import 'package:shadcn_ui/shadcn_ui.dart';
import '../../../../core/config/environment.dart';
import '../../../../core/constants/app_sections.dart';
import '../../../../core/permissions/permission_manager.dart';
import '../../../../core/permissions/permission_resources.dart';
import '../../../../widgets/app_layout.dart';
import '../../../../widgets/components/feedback.dart';
import '../../../../widgets/components/filter_bar.dart';
@@ -18,9 +19,10 @@ import '../../domain/entities/approval.dart';
import '../../domain/entities/approval_template.dart';
import '../../domain/repositories/approval_repository.dart';
import '../../domain/repositories/approval_template_repository.dart';
import '../../../inventory/lookups/domain/repositories/inventory_lookup_repository.dart';
import '../controllers/approval_controller.dart';
const _approvalsResourcePath = '/approvals/requests';
const _approvalsResourcePath = PermissionResources.approvals;
/// 결재 관리 최상위 페이지.
///
@@ -85,11 +87,15 @@ class _ApprovalEnabledPageState extends State<_ApprovalEnabledPage> {
_controller = ApprovalController(
approvalRepository: GetIt.I<ApprovalRepository>(),
templateRepository: GetIt.I<ApprovalTemplateRepository>(),
lookupRepository: GetIt.I.isRegistered<InventoryLookupRepository>()
? GetIt.I<InventoryLookupRepository>()
: null,
)..addListener(_handleControllerUpdate);
WidgetsBinding.instance.addPostFrameCallback((_) async {
await Future.wait([
_controller.loadActionOptions(),
_controller.loadTemplates(),
_controller.loadStatusLookups(),
]);
await _controller.fetch();
});
@@ -335,6 +341,8 @@ class _ApprovalEnabledPageState extends State<_ApprovalEnabledPage> {
selectedTemplateId: _selectedTemplateId,
canPerformStepActions: canPerformStepActions,
canApplyTemplate: canManageTemplates,
canProceed: _controller.canProceedSelected,
cannotProceedReason: _controller.cannotProceedReason,
dateFormat: _dateTimeFormat,
onRefresh: () {
final id = selectedApproval?.id;
@@ -660,22 +668,8 @@ class _ApprovalEnabledPageState extends State<_ApprovalEnabledPage> {
return confirmed ?? false;
}
String _statusLabel(ApprovalStatusFilter filter) {
switch (filter) {
case ApprovalStatusFilter.all:
return '전체 상태';
case ApprovalStatusFilter.pending:
return '대기';
case ApprovalStatusFilter.inProgress:
return '진행중';
case ApprovalStatusFilter.onHold:
return '보류';
case ApprovalStatusFilter.approved:
return '승인';
case ApprovalStatusFilter.rejected:
return '반려';
}
}
String _statusLabel(ApprovalStatusFilter filter) =>
_controller.statusLabel(filter);
String _dialogTitle(ApprovalStepActionType type) {
switch (type) {
@@ -827,6 +821,8 @@ class _DetailSection extends StatelessWidget {
required this.selectedTemplateId,
required this.canPerformStepActions,
required this.canApplyTemplate,
required this.canProceed,
required this.cannotProceedReason,
required this.dateFormat,
required this.onRefresh,
required this.onClose,
@@ -849,6 +845,8 @@ class _DetailSection extends StatelessWidget {
final int? selectedTemplateId;
final bool canPerformStepActions;
final bool canApplyTemplate;
final bool canProceed;
final String? cannotProceedReason;
final intl.DateFormat dateFormat;
final VoidCallback onRefresh;
final VoidCallback? onClose;
@@ -929,6 +927,8 @@ class _DetailSection extends StatelessWidget {
selectedTemplateId: selectedTemplateId,
canPerformStepActions: canPerformStepActions,
canApplyTemplate: canApplyTemplate,
canProceed: canProceed,
cannotProceedReason: cannotProceedReason,
onSelectTemplate: onSelectTemplate,
onApplyTemplate: onApplyTemplate,
onReloadTemplates: onReloadTemplates,
@@ -1028,6 +1028,8 @@ class _StepTab extends StatelessWidget {
required this.selectedTemplateId,
required this.canPerformStepActions,
required this.canApplyTemplate,
required this.canProceed,
required this.cannotProceedReason,
required this.onSelectTemplate,
required this.onApplyTemplate,
required this.onReloadTemplates,
@@ -1048,6 +1050,8 @@ class _StepTab extends StatelessWidget {
final int? selectedTemplateId;
final bool canPerformStepActions;
final bool canApplyTemplate;
final bool canProceed;
final String? cannotProceedReason;
final void Function(int?) onSelectTemplate;
final void Function(int templateId) onApplyTemplate;
final VoidCallback onReloadTemplates;
@@ -1097,6 +1101,14 @@ class _StepTab extends StatelessWidget {
style: theme.textTheme.muted,
),
),
if (!canProceed)
Padding(
padding: const EdgeInsets.fromLTRB(20, 0, 20, 12),
child: Text(
cannotProceedReason ?? '현재는 결재 단계를 진행할 수 없습니다.',
style: theme.textTheme.muted,
),
),
if (steps.isEmpty)
Expanded(
child: Center(
@@ -1112,6 +1124,8 @@ class _StepTab extends StatelessWidget {
final disabledReason = _disabledReason(
step,
canPerformStepActions,
canProceed,
cannotProceedReason,
);
final isProcessingStep =
isPerformingAction && processingStepId == step.id;
@@ -1284,7 +1298,12 @@ class _StepTab extends StatelessWidget {
return button;
}
String? _disabledReason(ApprovalStep step, bool canPerformStepActions) {
String? _disabledReason(
ApprovalStep step,
bool canPerformStepActions,
bool canProceed,
String? cannotProceedReason,
) {
if (!canPerformStepActions) {
return '결재 행위를 수행할 권한이 없습니다.';
}
@@ -1294,6 +1313,9 @@ class _StepTab extends StatelessWidget {
if (!hasActionOptions) {
return '사용 가능한 결재 행위가 없습니다.';
}
if (!canProceed) {
return cannotProceedReason ?? '현재는 결재 단계를 진행할 수 없습니다.';
}
if (isPerformingAction && processingStepId != step.id) {
return '다른 결재 단계를 처리 중입니다.';
}