refactor: UI 화면 통합 및 불필요한 파일 정리
Some checks failed
Flutter Test & Quality Check / Build APK (push) Has been cancelled
Flutter Test & Quality Check / Test on macos-latest (push) Has been cancelled
Flutter Test & Quality Check / Test on ubuntu-latest (push) Has been cancelled

- 모든 *_redesign.dart 파일을 기본 화면 파일로 통합
- 백업용 컨트롤러 파일들 제거 (*_controller.backup.dart)
- 사용하지 않는 예제 및 테스트 파일 제거
- Clean Architecture 적용 후 남은 정리 작업 완료
- 테스트 코드 정리 및 구조 개선 준비

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
JiWoong Sul
2025-08-11 14:00:44 +09:00
parent 162fe08618
commit 1e6da44917
103 changed files with 1224 additions and 2976 deletions

View File

@@ -123,10 +123,10 @@ class EquipmentInFormController extends ChangeNotifier {
void _loadWarehouseLocations() async {
try {
DebugLogger.log('입고지 목록 API 로드 시작', tag: 'EQUIPMENT_IN');
final locations = await _warehouseService.getWarehouseLocations();
warehouseLocations = locations.map((e) => e.name).toList();
final response = await _warehouseService.getWarehouseLocations();
warehouseLocations = response.items.map((e) => e.name).toList();
// 이름-ID 매핑 저장
warehouseLocationMap = {for (var loc in locations) loc.name: loc.id};
warehouseLocationMap = {for (var loc in response.items) loc.name: loc.id};
DebugLogger.log('입고지 목록 로드 성공', tag: 'EQUIPMENT_IN', data: {
'count': warehouseLocations.length,
'locations': warehouseLocations,
@@ -146,8 +146,8 @@ class EquipmentInFormController extends ChangeNotifier {
void _loadPartnerCompanies() async {
try {
DebugLogger.log('파트너사 목록 API 로드 시작', tag: 'EQUIPMENT_IN');
final companies = await _companyService.getCompanies();
partnerCompanies = companies.map((c) => c.name).toList();
final response = await _companyService.getCompanies();
partnerCompanies = response.items.map((c) => c.name).toList();
DebugLogger.log('파트너사 목록 로드 성공', tag: 'EQUIPMENT_IN', data: {
'count': partnerCompanies.length,
'companies': partnerCompanies,

View File

@@ -1,281 +0,0 @@
import 'package:flutter/foundation.dart';
import 'package:get_it/get_it.dart';
import 'package:superport/models/equipment_unified_model.dart';
import 'package:superport/services/equipment_service.dart';
import 'package:superport/utils/constants.dart';
import 'package:superport/core/errors/failures.dart';
import 'package:superport/models/equipment_unified_model.dart' as legacy;
import 'package:superport/core/utils/debug_logger.dart';
// companyTypeToString 함수 import
import 'package:superport/utils/constants.dart'
show companyTypeToString, CompanyType;
import 'package:superport/models/company_model.dart';
import 'package:superport/models/address_model.dart';
import 'package:superport/core/utils/equipment_status_converter.dart';
// 장비 목록 화면의 상태 및 비즈니스 로직을 담당하는 컨트롤러
class EquipmentListController extends ChangeNotifier {
final EquipmentService _equipmentService = GetIt.instance<EquipmentService>();
List<UnifiedEquipment> equipments = [];
String? selectedStatusFilter;
String searchKeyword = ''; // 검색어 추가
final Set<String> selectedEquipmentIds = {}; // 'id:status' 형식
bool _isLoading = false;
String? _error;
// API만 사용
// 페이지네이션
int _currentPage = 1;
final int _perPage = 20;
bool _hasMore = true;
// Getters
bool get isLoading => _isLoading;
String? get error => _error;
bool get hasMore => _hasMore;
int get currentPage => _currentPage;
EquipmentListController();
// 데이터 로드 및 상태 필터 적용
Future<void> loadData({bool isRefresh = false, String? search}) async {
if (_isLoading) return;
_isLoading = true;
_error = null;
notifyListeners();
try {
// API 호출 - 전체 데이터 로드
print('╔══════════════════════════════════════════════════════════');
print('║ 📦 장비 목록 API 호출 시작');
print('║ • 상태 필터: ${selectedStatusFilter ?? "전체"}');
print('║ • 검색어: ${search ?? searchKeyword}');
print('╚══════════════════════════════════════════════════════════');
// 전체 데이터를 가져오기 위해 큰 perPage 값 사용
final apiEquipmentDtos = await _equipmentService.getEquipmentsWithStatus(
page: 1,
perPage: 1000, // 충분히 큰 값으로 전체 데이터 로드
status: selectedStatusFilter != null ? EquipmentStatusConverter.clientToServer(selectedStatusFilter) : null,
search: search ?? searchKeyword,
);
print('╔══════════════════════════════════════════════════════════');
print('║ 📊 장비 목록 로드 완료');
print('║ ▶ 총 장비 수: ${apiEquipmentDtos.length}');
print('╟──────────────────────────────────────────────────────────');
// 상태별 통계
Map<String, int> statusCount = {};
for (final dto in apiEquipmentDtos) {
final clientStatus = EquipmentStatusConverter.serverToClient(dto.status);
statusCount[clientStatus] = (statusCount[clientStatus] ?? 0) + 1;
}
statusCount.forEach((status, count) {
print('║ • $status: $count개');
});
print('╟──────────────────────────────────────────────────────────');
print('║ 📑 전체 데이터 로드 완료');
print('║ • View에서 페이지네이션 처리 예정');
print('╚══════════════════════════════════════════════════════════');
// DTO를 UnifiedEquipment로 변환 (status 정보 포함)
final List<UnifiedEquipment> unifiedEquipments = apiEquipmentDtos.map((dto) {
final equipment = Equipment(
id: dto.id,
manufacturer: dto.manufacturer,
name: dto.modelName ?? dto.equipmentNumber,
category: '', // 세부 정보는 상세 조회에서 가져와야 함
subCategory: '',
subSubCategory: '',
serialNumber: dto.serialNumber,
quantity: 1,
inDate: dto.createdAt,
);
return UnifiedEquipment(
id: dto.id,
equipment: equipment,
date: dto.createdAt,
status: EquipmentStatusConverter.serverToClient(dto.status), // 서버 status를 클라이언트 status로 변환
);
}).toList();
equipments = unifiedEquipments;
_hasMore = false; // 전체 데이터를 로드했으므로 더 이상 로드할 필요 없음
selectedEquipmentIds.clear();
} on Failure catch (e) {
_error = e.message;
} catch (e) {
_error = 'An unexpected error occurred: $e';
} finally {
_isLoading = false;
notifyListeners();
}
}
// 상태 필터 변경
Future<void> changeStatusFilter(String? status) async {
selectedStatusFilter = status;
await loadData(isRefresh: true);
}
// 검색어 변경
Future<void> updateSearchKeyword(String keyword) async {
searchKeyword = keyword;
await loadData(isRefresh: true, search: keyword);
}
// 장비 선택/해제 (모든 상태 지원)
void selectEquipment(int? id, String status, bool? isSelected) {
if (id == null || isSelected == null) return;
final key = '$id:$status';
if (isSelected) {
selectedEquipmentIds.add(key);
} else {
selectedEquipmentIds.remove(key);
}
notifyListeners();
}
// 선택된 입고 장비 수 반환
int getSelectedInStockCount() {
int count = 0;
for (final idStatusPair in selectedEquipmentIds) {
final parts = idStatusPair.split(':');
if (parts.length == 2 && parts[1] == EquipmentStatus.in_) {
count++;
}
}
return count;
}
// 선택된 전체 장비 수 반환
int getSelectedEquipmentCount() {
return selectedEquipmentIds.length;
}
// 선택된 특정 상태의 장비 수 반환
int getSelectedEquipmentCountByStatus(String status) {
int count = 0;
for (final idStatusPair in selectedEquipmentIds) {
final parts = idStatusPair.split(':');
if (parts.length == 2 && parts[1] == status) {
count++;
}
}
return count;
}
// 선택된 장비들의 UnifiedEquipment 객체 목록 반환
List<UnifiedEquipment> getSelectedEquipments() {
List<UnifiedEquipment> selected = [];
for (final idStatusPair in selectedEquipmentIds) {
final parts = idStatusPair.split(':');
if (parts.length == 2) {
final id = int.tryParse(parts[0]);
if (id != null) {
final equipment = equipments.firstWhere(
(e) => e.id == id && e.status == parts[1],
orElse: () => null as UnifiedEquipment,
);
if (equipment != null) {
selected.add(equipment);
}
}
}
}
return selected;
}
// 선택된 특정 상태의 장비들의 UnifiedEquipment 객체 목록 반환
List<UnifiedEquipment> getSelectedEquipmentsByStatus(String status) {
List<UnifiedEquipment> selected = [];
for (final idStatusPair in selectedEquipmentIds) {
final parts = idStatusPair.split(':');
if (parts.length == 2 && parts[1] == status) {
final id = int.tryParse(parts[0]);
if (id != null) {
final equipment = equipments.firstWhere(
(e) => e.id == id && e.status == status,
orElse: () => null as UnifiedEquipment,
);
if (equipment != null) {
selected.add(equipment);
}
}
}
}
return selected;
}
// 선택된 장비들의 요약 정보를 Map 형태로 반환 (출고/대여/폐기 폼에서 사용)
List<Map<String, dynamic>> getSelectedEquipmentsSummary() {
List<Map<String, dynamic>> summaryList = [];
List<UnifiedEquipment> selectedEquipmentsInStock =
getSelectedEquipmentsByStatus(EquipmentStatus.in_);
for (final equipment in selectedEquipmentsInStock) {
summaryList.add({
'equipment': equipment.equipment,
'equipmentInId': equipment.id,
'status': equipment.status,
});
}
return summaryList;
}
// 출고 정보(회사, 담당자, 라이센스 등) 반환
// 출고 정보는 API를 통해 번별로 조회해야 하므로 별도 서비스로 분리 예정
String getOutEquipmentInfo(int equipmentId, String infoType) {
// TODO: API로 출고 정보 조회 구현
return '-';
}
// 장비 삭제
Future<bool> deleteEquipment(UnifiedEquipment equipment) async {
try {
// API를 통한 삭제
if (equipment.equipment.id != null) {
await _equipmentService.deleteEquipment(equipment.equipment.id!);
} else {
throw Exception('Equipment ID is null');
}
// 로컬 리스트에서도 제거
equipments.removeWhere((e) => e.id == equipment.id && e.status == equipment.status);
notifyListeners();
return true;
} on Failure catch (e) {
_error = e.message;
notifyListeners();
return false;
} catch (e) {
_error = 'Failed to delete equipment: $e';
notifyListeners();
return false;
}
}
// API만 사용하므로 토글 기능 제거
// 에러 처리
void clearError() {
_error = null;
notifyListeners();
}
@override
void dispose() {
super.dispose();
}
}

View File

@@ -79,7 +79,7 @@ class EquipmentListController extends BaseListController<UnifiedEquipment> {
}
// DTO를 UnifiedEquipment로 변환
final items = apiEquipmentDtos.map((dto) {
final items = apiEquipmentDtos.items.map((dto) {
final equipment = Equipment(
id: dto.id,
manufacturer: dto.manufacturer ?? 'Unknown',
@@ -109,7 +109,7 @@ class EquipmentListController extends BaseListController<UnifiedEquipment> {
perPage: params.perPage,
total: items.length < params.perPage ?
(params.page - 1) * params.perPage + items.length :
params.page * params.perPage + 1,
(params.page * params.perPage) + 1,
totalPages: items.length < params.perPage ? params.page : params.page + 1,
hasNext: items.length >= params.perPage,
hasPrevious: params.page > 1,

View File

@@ -79,8 +79,8 @@ class EquipmentOutFormController extends ChangeNotifier {
Future<void> loadDropdownData() async {
try {
// API를 통해 회사 목록 로드
final allCompanies = await _companyService.getCompanies();
companies = allCompanies
final response = await _companyService.getCompanies();
companies = response.items
.where((c) => c.companyTypes.contains(CompanyType.customer))
.map((c) => CompanyBranchInfo(
id: c.id,
@@ -204,9 +204,9 @@ class EquipmentOutFormController extends ChangeNotifier {
// 선택된 회사 정보에서 ID 추출
if (selectedCompanies[0] != null) {
final companies = await companyService.getCompanies(search: selectedCompanies[0]);
if (companies.isNotEmpty) {
companyId = companies.first.id;
final response = await companyService.getCompanies(search: selectedCompanies[0]);
if (response.items.isNotEmpty) {
companyId = response.items.first.id;
// TODO: 지점 ID 처리 로직 추가
}
}