Files
superport/lib/domain/entities/company_hierarchy.dart

146 lines
3.6 KiB
Dart

import 'package:freezed_annotation/freezed_annotation.dart';
part 'company_hierarchy.freezed.dart';
/// Company 계층 구조 도메인 엔티티
@freezed
class CompanyHierarchy with _$CompanyHierarchy {
const CompanyHierarchy._();
const factory CompanyHierarchy({
required String id,
required String name,
String? parentId,
String? parentName,
@Default([]) List<CompanyHierarchy> children,
@Default(0) int level,
@Default('') String fullPath,
@Default(false) bool isExpanded,
@Default(0) int totalDescendants,
}) = _CompanyHierarchy;
/// 계층 구조에서 특정 회사 찾기
CompanyHierarchy? findCompany(String companyId) {
if (id == companyId) {
return this;
}
for (final child in children) {
final found = child.findCompany(companyId);
if (found != null) {
return found;
}
}
return null;
}
/// 모든 자손 회사 ID 목록 가져오기
List<String> getAllDescendantIds() {
final ids = <String>[];
for (final child in children) {
ids.add(child.id);
ids.addAll(child.getAllDescendantIds());
}
return ids;
}
/// 특정 회사가 자손인지 확인
bool hasDescendant(String companyId) {
return getAllDescendantIds().contains(companyId);
}
/// 계층 구조의 최대 깊이 계산
int getMaxDepth() {
if (children.isEmpty) {
return level;
}
return children
.map((child) => child.getMaxDepth())
.reduce((max, depth) => depth > max ? depth : max);
}
/// 순환 참조 검증
bool wouldCreateCycle(String newParentId) {
// 자기 자신을 부모로 설정하려는 경우
if (id == newParentId) {
return true;
}
// 자손을 부모로 설정하려는 경우
if (hasDescendant(newParentId)) {
return true;
}
return false;
}
/// 계층 경로 생성
String buildPath(String separator) {
final parts = fullPath.split('/').where((p) => p.isNotEmpty).toList();
return parts.join(separator);
}
/// 평면 리스트로 변환 (트리 구조 → 플랫 리스트)
List<CompanyHierarchy> flatten() {
final flatList = <CompanyHierarchy>[this];
for (final child in children) {
flatList.addAll(child.flatten());
}
return flatList;
}
/// 계층 구조 통계
Map<String, dynamic> getStatistics() {
final flat = flatten();
return {
'totalCompanies': flat.length,
'maxDepth': getMaxDepth(),
'directChildren': children.length,
'totalDescendants': totalDescendants,
'levels': _getLevelDistribution(flat),
};
}
Map<int, int> _getLevelDistribution(List<CompanyHierarchy> companies) {
final distribution = <int, int>{};
for (final company in companies) {
distribution[company.level] = (distribution[company.level] ?? 0) + 1;
}
return distribution;
}
}
/// 계층 구조 검증 결과
@freezed
class HierarchyValidationResult with _$HierarchyValidationResult {
const factory HierarchyValidationResult({
required bool isValid,
@Default('') String message,
@Default([]) List<String> errors,
@Default([]) List<String> warnings,
}) = _HierarchyValidationResult;
factory HierarchyValidationResult.valid() => const HierarchyValidationResult(
isValid: true,
message: 'Hierarchy is valid',
);
factory HierarchyValidationResult.invalid({
required String message,
List<String> errors = const [],
List<String> warnings = const [],
}) => HierarchyValidationResult(
isValid: false,
message: message,
errors: errors,
warnings: warnings,
);
}