feat: 결재·마스터 실연동 업데이트
This commit is contained in:
@@ -32,7 +32,9 @@ class GroupDto {
|
||||
return GroupDto(
|
||||
id: json['id'] as int?,
|
||||
groupName: json['group_name'] as String,
|
||||
description: json['description'] as String?,
|
||||
description:
|
||||
json['description'] as String? ??
|
||||
json['group_description'] as String?,
|
||||
isDefault: (json['is_default'] as bool?) ?? false,
|
||||
isActive: (json['is_active'] as bool?) ?? true,
|
||||
isDeleted: (json['is_deleted'] as bool?) ?? false,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:superport_v2/core/common/models/paginated_result.dart';
|
||||
import 'package:superport_v2/core/network/api_client.dart';
|
||||
import 'package:superport_v2/core/network/api_routes.dart';
|
||||
|
||||
import '../../domain/entities/group.dart';
|
||||
import '../../domain/repositories/group_repository.dart';
|
||||
@@ -12,7 +13,7 @@ class GroupRepositoryRemote implements GroupRepository {
|
||||
|
||||
final ApiClient _api;
|
||||
|
||||
static const _basePath = '/groups';
|
||||
static const _basePath = '${ApiRoutes.apiV1}/groups';
|
||||
|
||||
/// 그룹 목록을 조회한다.
|
||||
@override
|
||||
@@ -22,7 +23,16 @@ class GroupRepositoryRemote implements GroupRepository {
|
||||
String? query,
|
||||
bool? isDefault,
|
||||
bool? isActive,
|
||||
bool includePermissions = false,
|
||||
bool includeEmployees = false,
|
||||
}) async {
|
||||
final includeParts = <String>[];
|
||||
if (includePermissions) {
|
||||
includeParts.add('permissions');
|
||||
}
|
||||
if (includeEmployees) {
|
||||
includeParts.add('employees');
|
||||
}
|
||||
final response = await _api.get<Map<String, dynamic>>(
|
||||
_basePath,
|
||||
query: {
|
||||
@@ -31,6 +41,7 @@ class GroupRepositoryRemote implements GroupRepository {
|
||||
if (query != null && query.isNotEmpty) 'q': query,
|
||||
if (isDefault != null) 'is_default': isDefault,
|
||||
if (isActive != null) 'is_active': isActive,
|
||||
if (includeParts.isNotEmpty) 'include': includeParts.join(','),
|
||||
},
|
||||
options: Options(responseType: ResponseType.json),
|
||||
);
|
||||
|
||||
@@ -10,6 +10,8 @@ abstract class GroupRepository {
|
||||
String? query,
|
||||
bool? isDefault,
|
||||
bool? isActive,
|
||||
bool includePermissions = false,
|
||||
bool includeEmployees = false,
|
||||
});
|
||||
|
||||
/// 그룹 신규 등록
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:superport_v2/core/common/models/paginated_result.dart';
|
||||
import 'package:superport_v2/core/network/failure.dart';
|
||||
|
||||
import 'package:superport_v2/core/permissions/permission_manager.dart';
|
||||
|
||||
import '../../domain/entities/group.dart';
|
||||
import '../../domain/repositories/group_repository.dart';
|
||||
import '../../../group_permission/application/permission_synchronizer.dart';
|
||||
import '../../../group_permission/domain/repositories/group_permission_repository.dart';
|
||||
|
||||
/// 기본 그룹 여부 필터.
|
||||
enum GroupDefaultFilter { all, defaultOnly, nonDefault }
|
||||
@@ -15,10 +20,17 @@ enum GroupStatusFilter { all, activeOnly, inactiveOnly }
|
||||
/// - 목록 조회 및 필터, 페이징 상태를 담당한다.
|
||||
/// - 생성/수정/삭제/복구 요청을 래핑하여 UI와 통신한다.
|
||||
class GroupController extends ChangeNotifier {
|
||||
GroupController({required GroupRepository repository})
|
||||
: _repository = repository;
|
||||
GroupController({
|
||||
required GroupRepository repository,
|
||||
GroupPermissionRepository? permissionRepository,
|
||||
PermissionManager? permissionManager,
|
||||
}) : _repository = repository,
|
||||
_permissionRepository = permissionRepository,
|
||||
_permissionManager = permissionManager;
|
||||
|
||||
final GroupRepository _repository;
|
||||
final GroupPermissionRepository? _permissionRepository;
|
||||
final PermissionManager? _permissionManager;
|
||||
|
||||
PaginatedResult<Group>? _result;
|
||||
bool _isLoading = false;
|
||||
@@ -60,8 +72,9 @@ class GroupController extends ChangeNotifier {
|
||||
isActive: isActive,
|
||||
);
|
||||
_result = response;
|
||||
} catch (e) {
|
||||
_errorMessage = e.toString();
|
||||
} catch (error) {
|
||||
final failure = Failure.from(error);
|
||||
_errorMessage = failure.describe();
|
||||
} finally {
|
||||
_isLoading = false;
|
||||
notifyListeners();
|
||||
@@ -92,9 +105,11 @@ class GroupController extends ChangeNotifier {
|
||||
try {
|
||||
final created = await _repository.create(input);
|
||||
await fetch(page: 1);
|
||||
await _maybeSync(created.id);
|
||||
return created;
|
||||
} catch (e) {
|
||||
_errorMessage = e.toString();
|
||||
} catch (error) {
|
||||
final failure = Failure.from(error);
|
||||
_errorMessage = failure.describe();
|
||||
notifyListeners();
|
||||
return null;
|
||||
} finally {
|
||||
@@ -108,9 +123,11 @@ class GroupController extends ChangeNotifier {
|
||||
try {
|
||||
final updated = await _repository.update(id, input);
|
||||
await fetch(page: _result?.page ?? 1);
|
||||
await _maybeSync(updated.id);
|
||||
return updated;
|
||||
} catch (e) {
|
||||
_errorMessage = e.toString();
|
||||
} catch (error) {
|
||||
final failure = Failure.from(error);
|
||||
_errorMessage = failure.describe();
|
||||
notifyListeners();
|
||||
return null;
|
||||
} finally {
|
||||
@@ -124,9 +141,11 @@ class GroupController extends ChangeNotifier {
|
||||
try {
|
||||
await _repository.delete(id);
|
||||
await fetch(page: _result?.page ?? 1);
|
||||
await _maybeSync(id);
|
||||
return true;
|
||||
} catch (e) {
|
||||
_errorMessage = e.toString();
|
||||
} catch (error) {
|
||||
final failure = Failure.from(error);
|
||||
_errorMessage = failure.describe();
|
||||
notifyListeners();
|
||||
return false;
|
||||
} finally {
|
||||
@@ -140,9 +159,11 @@ class GroupController extends ChangeNotifier {
|
||||
try {
|
||||
final restored = await _repository.restore(id);
|
||||
await fetch(page: _result?.page ?? 1);
|
||||
await _maybeSync(restored.id);
|
||||
return restored;
|
||||
} catch (e) {
|
||||
_errorMessage = e.toString();
|
||||
} catch (error) {
|
||||
final failure = Failure.from(error);
|
||||
_errorMessage = failure.describe();
|
||||
notifyListeners();
|
||||
return null;
|
||||
} finally {
|
||||
@@ -161,4 +182,28 @@ class GroupController extends ChangeNotifier {
|
||||
_isSubmitting = value;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<void> _maybeSync(int? groupId) async {
|
||||
if (groupId == null) {
|
||||
return;
|
||||
}
|
||||
await _syncPermissionsForGroup(groupId);
|
||||
}
|
||||
|
||||
Future<void> _syncPermissionsForGroup(int groupId) async {
|
||||
final repository = _permissionRepository;
|
||||
final manager = _permissionManager;
|
||||
if (repository == null || manager == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
final synchronizer = PermissionSynchronizer(
|
||||
repository: repository,
|
||||
manager: manager,
|
||||
);
|
||||
await synchronizer.syncForGroup(groupId);
|
||||
} catch (_) {
|
||||
// 권한 동기화 실패는 UI 동작에 영향을 주지 않도록 무시한다.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user