프로젝트 최초 커밋
This commit is contained in:
@@ -0,0 +1,267 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:superport/models/equipment_unified_model.dart';
|
||||
import 'package:superport/models/company_model.dart';
|
||||
import 'package:superport/services/mock_data_service.dart';
|
||||
import 'package:superport/utils/constants.dart';
|
||||
|
||||
/// 장비 입고 폼 컨트롤러
|
||||
///
|
||||
/// 폼의 전체 상태, 유효성, 저장, 데이터 로딩 등 비즈니스 로직을 담당한다.
|
||||
class EquipmentInFormController {
|
||||
final MockDataService dataService;
|
||||
final int? equipmentInId;
|
||||
|
||||
// 폼 키
|
||||
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
|
||||
|
||||
// 입력 상태 변수
|
||||
String manufacturer = '';
|
||||
String name = '';
|
||||
String category = '';
|
||||
String subCategory = '';
|
||||
String subSubCategory = '';
|
||||
String serialNumber = '';
|
||||
String barcode = '';
|
||||
int quantity = 1;
|
||||
DateTime inDate = DateTime.now();
|
||||
String equipmentType = EquipmentType.new_;
|
||||
bool hasSerialNumber = true;
|
||||
|
||||
// 워런티 관련 상태
|
||||
String? warrantyLicense;
|
||||
String? warrantyCode; // 워런티 코드(텍스트 입력)
|
||||
DateTime warrantyStartDate = DateTime.now();
|
||||
DateTime warrantyEndDate = DateTime.now().add(const Duration(days: 365));
|
||||
List<String> warrantyLicenses = [];
|
||||
|
||||
// 자동완성 데이터
|
||||
List<String> manufacturers = [];
|
||||
List<String> equipmentNames = [];
|
||||
// 카테고리 자동완성 데이터
|
||||
List<String> categories = [];
|
||||
List<String> subCategories = [];
|
||||
List<String> subSubCategories = [];
|
||||
|
||||
// 편집 모드 여부
|
||||
bool isEditMode = false;
|
||||
|
||||
// 입고지, 파트너사 관련 상태
|
||||
String? warehouseLocation;
|
||||
String? partnerCompany;
|
||||
List<String> warehouseLocations = [];
|
||||
List<String> partnerCompanies = [];
|
||||
|
||||
final TextEditingController remarkController = TextEditingController();
|
||||
|
||||
EquipmentInFormController({required this.dataService, this.equipmentInId}) {
|
||||
isEditMode = equipmentInId != null;
|
||||
_loadManufacturers();
|
||||
_loadEquipmentNames();
|
||||
_loadCategories();
|
||||
_loadSubCategories();
|
||||
_loadSubSubCategories();
|
||||
_loadWarehouseLocations();
|
||||
_loadPartnerCompanies();
|
||||
_loadWarrantyLicenses();
|
||||
if (isEditMode) {
|
||||
_loadEquipmentIn();
|
||||
}
|
||||
}
|
||||
|
||||
// 제조사 목록 로드
|
||||
void _loadManufacturers() {
|
||||
manufacturers = dataService.getAllManufacturers();
|
||||
}
|
||||
|
||||
// 장비명 목록 로드
|
||||
void _loadEquipmentNames() {
|
||||
equipmentNames = dataService.getAllEquipmentNames();
|
||||
}
|
||||
|
||||
// 카테고리 목록 로드
|
||||
void _loadCategories() {
|
||||
categories = dataService.getAllCategories();
|
||||
}
|
||||
|
||||
// 서브카테고리 목록 로드
|
||||
void _loadSubCategories() {
|
||||
subCategories = dataService.getAllSubCategories();
|
||||
}
|
||||
|
||||
// 서브서브카테고리 목록 로드
|
||||
void _loadSubSubCategories() {
|
||||
subSubCategories = dataService.getAllSubSubCategories();
|
||||
}
|
||||
|
||||
// 입고지 목록 로드
|
||||
void _loadWarehouseLocations() {
|
||||
warehouseLocations =
|
||||
dataService.getAllWarehouseLocations().map((e) => e.name).toList();
|
||||
}
|
||||
|
||||
// 파트너사 목록 로드
|
||||
void _loadPartnerCompanies() {
|
||||
partnerCompanies =
|
||||
dataService
|
||||
.getAllCompanies()
|
||||
.where((c) => c.companyTypes.contains(CompanyType.partner))
|
||||
.map((c) => c.name)
|
||||
.toList();
|
||||
}
|
||||
|
||||
// 워런티 라이센스 목록 로드
|
||||
void _loadWarrantyLicenses() {
|
||||
// 실제로는 API나 서비스에서 불러와야 하지만, 파트너사와 동일한 데이터 사용
|
||||
warrantyLicenses = List.from(partnerCompanies);
|
||||
}
|
||||
|
||||
// 기존 데이터 로드(수정 모드)
|
||||
void _loadEquipmentIn() {
|
||||
final equipmentIn = dataService.getEquipmentInById(equipmentInId!);
|
||||
if (equipmentIn != null) {
|
||||
manufacturer = equipmentIn.equipment.manufacturer;
|
||||
name = equipmentIn.equipment.name;
|
||||
category = equipmentIn.equipment.category;
|
||||
subCategory = equipmentIn.equipment.subCategory;
|
||||
subSubCategory = equipmentIn.equipment.subSubCategory;
|
||||
serialNumber = equipmentIn.equipment.serialNumber ?? '';
|
||||
barcode = equipmentIn.equipment.barcode ?? '';
|
||||
quantity = equipmentIn.equipment.quantity;
|
||||
inDate = equipmentIn.inDate;
|
||||
hasSerialNumber = serialNumber.isNotEmpty;
|
||||
equipmentType = equipmentIn.type;
|
||||
warehouseLocation = equipmentIn.warehouseLocation;
|
||||
partnerCompany = equipmentIn.partnerCompany;
|
||||
remarkController.text = equipmentIn.remark ?? '';
|
||||
|
||||
// 워런티 정보 로드 (실제 구현에서는 기존 값을 불러옵니다)
|
||||
warrantyLicense = equipmentIn.partnerCompany; // 기본값으로 파트너사 이름 사용
|
||||
warrantyStartDate = equipmentIn.inDate;
|
||||
warrantyEndDate = equipmentIn.inDate.add(const Duration(days: 365));
|
||||
// 워런티 코드도 불러오도록(실제 구현시)
|
||||
warrantyCode = null; // TODO: 실제 데이터에서 불러올 경우 수정
|
||||
}
|
||||
}
|
||||
|
||||
// 워런티 기간 계산
|
||||
String getWarrantyPeriodSummary() {
|
||||
final difference = warrantyEndDate.difference(warrantyStartDate);
|
||||
final days = difference.inDays;
|
||||
|
||||
if (days <= 0) {
|
||||
return '유효하지 않은 기간';
|
||||
}
|
||||
|
||||
final years = days ~/ 365;
|
||||
final remainingDays = days % 365;
|
||||
|
||||
String summary = '';
|
||||
if (years > 0) {
|
||||
summary += '$years년 ';
|
||||
}
|
||||
if (remainingDays > 0) {
|
||||
summary += '$remainingDays일';
|
||||
}
|
||||
|
||||
return summary.trim();
|
||||
}
|
||||
|
||||
// 저장 처리
|
||||
bool save() {
|
||||
if (!formKey.currentState!.validate()) {
|
||||
return false;
|
||||
}
|
||||
formKey.currentState!.save();
|
||||
|
||||
// 입력값이 리스트에 없으면 추가
|
||||
if (partnerCompany != null &&
|
||||
partnerCompany!.isNotEmpty &&
|
||||
!partnerCompanies.contains(partnerCompany)) {
|
||||
partnerCompanies.add(partnerCompany!);
|
||||
}
|
||||
if (warehouseLocation != null &&
|
||||
warehouseLocation!.isNotEmpty &&
|
||||
!warehouseLocations.contains(warehouseLocation)) {
|
||||
warehouseLocations.add(warehouseLocation!);
|
||||
}
|
||||
if (manufacturer.isNotEmpty && !manufacturers.contains(manufacturer)) {
|
||||
manufacturers.add(manufacturer);
|
||||
}
|
||||
if (name.isNotEmpty && !equipmentNames.contains(name)) {
|
||||
equipmentNames.add(name);
|
||||
}
|
||||
if (category.isNotEmpty && !categories.contains(category)) {
|
||||
categories.add(category);
|
||||
}
|
||||
if (subCategory.isNotEmpty && !subCategories.contains(subCategory)) {
|
||||
subCategories.add(subCategory);
|
||||
}
|
||||
if (subSubCategory.isNotEmpty &&
|
||||
!subSubCategories.contains(subSubCategory)) {
|
||||
subSubCategories.add(subSubCategory);
|
||||
}
|
||||
if (warrantyLicense != null &&
|
||||
warrantyLicense!.isNotEmpty &&
|
||||
!warrantyLicenses.contains(warrantyLicense)) {
|
||||
warrantyLicenses.add(warrantyLicense!);
|
||||
}
|
||||
|
||||
final equipment = Equipment(
|
||||
manufacturer: manufacturer,
|
||||
name: name,
|
||||
category: category,
|
||||
subCategory: subCategory,
|
||||
subSubCategory: subSubCategory,
|
||||
serialNumber: hasSerialNumber ? serialNumber : null,
|
||||
barcode: barcode.isNotEmpty ? barcode : null,
|
||||
quantity: quantity,
|
||||
remark: remarkController.text.trim(),
|
||||
warrantyLicense: warrantyLicense,
|
||||
warrantyStartDate: warrantyStartDate,
|
||||
warrantyEndDate: warrantyEndDate,
|
||||
// 워런티 코드 저장 필요시 여기에 추가
|
||||
);
|
||||
if (isEditMode) {
|
||||
final equipmentIn = dataService.getEquipmentInById(equipmentInId!);
|
||||
if (equipmentIn != null) {
|
||||
final updatedEquipmentIn = EquipmentIn(
|
||||
id: equipmentIn.id,
|
||||
equipment: equipment,
|
||||
inDate: inDate,
|
||||
status: equipmentIn.status,
|
||||
type: equipmentType,
|
||||
warehouseLocation: warehouseLocation,
|
||||
partnerCompany: partnerCompany,
|
||||
remark: remarkController.text.trim(),
|
||||
);
|
||||
dataService.updateEquipmentIn(updatedEquipmentIn);
|
||||
}
|
||||
} else {
|
||||
final newEquipmentIn = EquipmentIn(
|
||||
equipment: equipment,
|
||||
inDate: inDate,
|
||||
type: equipmentType,
|
||||
warehouseLocation: warehouseLocation,
|
||||
partnerCompany: partnerCompany,
|
||||
remark: remarkController.text.trim(),
|
||||
);
|
||||
dataService.addEquipmentIn(newEquipmentIn);
|
||||
}
|
||||
|
||||
// 저장 후 리스트 재로딩 (중복 방지 및 최신화)
|
||||
_loadManufacturers();
|
||||
_loadEquipmentNames();
|
||||
_loadCategories();
|
||||
_loadSubCategories();
|
||||
_loadSubSubCategories();
|
||||
_loadWarehouseLocations();
|
||||
_loadPartnerCompanies();
|
||||
_loadWarrantyLicenses();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void dispose() {
|
||||
remarkController.dispose();
|
||||
}
|
||||
}
|
||||
170
lib/screens/equipment/controllers/equipment_list_controller.dart
Normal file
170
lib/screens/equipment/controllers/equipment_list_controller.dart
Normal file
@@ -0,0 +1,170 @@
|
||||
import 'package:superport/models/equipment_unified_model.dart';
|
||||
import 'package:superport/services/mock_data_service.dart';
|
||||
import 'package:superport/utils/constants.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';
|
||||
|
||||
// 장비 목록 화면의 상태 및 비즈니스 로직을 담당하는 컨트롤러
|
||||
class EquipmentListController {
|
||||
final MockDataService dataService;
|
||||
List<UnifiedEquipment> equipments = [];
|
||||
String? selectedStatusFilter;
|
||||
final Set<String> selectedEquipmentIds = {}; // 'id:status' 형식
|
||||
|
||||
EquipmentListController({required this.dataService});
|
||||
|
||||
// 데이터 로드 및 상태 필터 적용
|
||||
void loadData() {
|
||||
equipments = dataService.getAllEquipments();
|
||||
if (selectedStatusFilter != null) {
|
||||
equipments =
|
||||
equipments.where((e) => e.status == selectedStatusFilter).toList();
|
||||
}
|
||||
selectedEquipmentIds.clear();
|
||||
}
|
||||
|
||||
// 상태 필터 변경
|
||||
void changeStatusFilter(String? status) {
|
||||
selectedStatusFilter = status;
|
||||
loadData();
|
||||
}
|
||||
|
||||
// 장비 선택/해제 (모든 상태 지원)
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
// 선택된 입고 장비 수 반환
|
||||
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;
|
||||
}
|
||||
|
||||
// 출고 정보(회사, 담당자, 라이센스 등) 반환
|
||||
String getOutEquipmentInfo(int equipmentId, String infoType) {
|
||||
final equipmentOut = dataService.getEquipmentOutById(equipmentId);
|
||||
if (equipmentOut != null) {
|
||||
switch (infoType) {
|
||||
case 'company':
|
||||
final company = equipmentOut.company ?? '-';
|
||||
if (company != '-') {
|
||||
final companyObj = dataService.getAllCompanies().firstWhere(
|
||||
(c) => c.name == company,
|
||||
orElse:
|
||||
() => Company(
|
||||
name: company,
|
||||
address: Address(),
|
||||
companyTypes: [CompanyType.customer], // 기본값 고객사
|
||||
),
|
||||
);
|
||||
// 여러 유형 중 첫 번째만 표시 (대표 유형)
|
||||
final typeText =
|
||||
companyObj.companyTypes.isNotEmpty
|
||||
? companyTypeToString(companyObj.companyTypes.first)
|
||||
: '-';
|
||||
return '$company (${typeText})';
|
||||
}
|
||||
return company;
|
||||
case 'manager':
|
||||
return equipmentOut.manager ?? '-';
|
||||
case 'license':
|
||||
return equipmentOut.license ?? '-';
|
||||
default:
|
||||
return '-';
|
||||
}
|
||||
}
|
||||
return '-';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,645 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:superport/models/equipment_unified_model.dart';
|
||||
import 'package:superport/models/company_model.dart';
|
||||
import 'package:superport/models/address_model.dart';
|
||||
import 'package:superport/services/mock_data_service.dart';
|
||||
|
||||
// 장비 출고 폼의 상태 및 비즈니스 로직을 담당하는 컨트롤러
|
||||
class EquipmentOutFormController {
|
||||
final MockDataService dataService;
|
||||
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
|
||||
final TextEditingController remarkController = TextEditingController();
|
||||
|
||||
// 상태 변수
|
||||
bool isEditMode = false;
|
||||
String manufacturer = '';
|
||||
String name = '';
|
||||
String category = '';
|
||||
String subCategory = '';
|
||||
String subSubCategory = '';
|
||||
String serialNumber = '';
|
||||
String barcode = '';
|
||||
int quantity = 1;
|
||||
DateTime outDate = DateTime.now();
|
||||
bool hasSerialNumber = false;
|
||||
DateTime? inDate;
|
||||
String returnType = '재입고';
|
||||
DateTime returnDate = DateTime.now();
|
||||
bool hasManagers = false;
|
||||
|
||||
// 출고 유형(출고/대여/폐기) 상태 변수 추가
|
||||
String outType = '출고'; // 기본값은 '출고'
|
||||
|
||||
// 기존 필드 - 호환성을 위해 유지
|
||||
String? _selectedCompany;
|
||||
String? get selectedCompany =>
|
||||
selectedCompanies.isNotEmpty ? selectedCompanies[0] : null;
|
||||
set selectedCompany(String? value) {
|
||||
if (selectedCompanies.isEmpty) {
|
||||
selectedCompanies.add(value);
|
||||
} else {
|
||||
selectedCompanies[0] = value;
|
||||
}
|
||||
_selectedCompany = value;
|
||||
}
|
||||
|
||||
String? _selectedManager;
|
||||
String? get selectedManager =>
|
||||
selectedManagersPerCompany.isNotEmpty
|
||||
? selectedManagersPerCompany[0]
|
||||
: null;
|
||||
set selectedManager(String? value) {
|
||||
if (selectedManagersPerCompany.isEmpty) {
|
||||
selectedManagersPerCompany.add(value);
|
||||
} else {
|
||||
selectedManagersPerCompany[0] = value;
|
||||
}
|
||||
_selectedManager = value;
|
||||
}
|
||||
|
||||
String? selectedLicense;
|
||||
List<String> companies = [];
|
||||
// 회사 및 지점 관련 데이터
|
||||
List<CompanyBranchInfo> companiesWithBranches = [];
|
||||
List<String> managers = [];
|
||||
List<String> filteredManagers = [];
|
||||
List<String> licenses = [];
|
||||
|
||||
// 출고 회사 목록 관리
|
||||
List<String?> selectedCompanies = [null]; // 첫 번째 드롭다운을 위한 초기값
|
||||
List<List<String>> availableCompaniesPerDropdown =
|
||||
[]; // 각 드롭다운마다 사용 가능한 회사 목록
|
||||
List<String?> selectedManagersPerCompany = [null]; // 각 드롭다운 회사별 선택된 담당자
|
||||
List<List<String>> filteredManagersPerCompany = []; // 각 드롭다운 회사별 필터링된 담당자 목록
|
||||
List<bool> hasManagersPerCompany = [false]; // 각 회사별 담당자 유무
|
||||
|
||||
// 입력 데이터
|
||||
Equipment? selectedEquipment;
|
||||
int? selectedEquipmentInId;
|
||||
int? equipmentOutId;
|
||||
List<Map<String, dynamic>>? _selectedEquipments;
|
||||
|
||||
EquipmentOutFormController({required this.dataService});
|
||||
|
||||
// 선택된 장비 정보 설정 (디버그용)
|
||||
set selectedEquipments(List<Map<String, dynamic>>? equipments) {
|
||||
debugPrint('설정된 장비 목록: ${equipments?.length ?? 0}개');
|
||||
if (equipments != null) {
|
||||
for (var i = 0; i < equipments.length; i++) {
|
||||
final equipment = equipments[i]['equipment'] as Equipment;
|
||||
debugPrint('장비 $i: ${equipment.manufacturer} ${equipment.name}');
|
||||
}
|
||||
}
|
||||
_selectedEquipments = equipments;
|
||||
}
|
||||
|
||||
List<Map<String, dynamic>>? get selectedEquipments => _selectedEquipments;
|
||||
|
||||
// 드롭다운 데이터 로드
|
||||
void loadDropdownData() {
|
||||
final allCompanies = dataService.getAllCompanies();
|
||||
|
||||
// 회사와 지점 통합 목록 생성
|
||||
companiesWithBranches = [];
|
||||
companies = [];
|
||||
|
||||
for (var company in allCompanies) {
|
||||
// 회사 자체 정보 추가
|
||||
final companyType =
|
||||
company.companyTypes.isNotEmpty
|
||||
? companyTypeToString(company.companyTypes.first)
|
||||
: '-';
|
||||
final companyInfo = CompanyBranchInfo(
|
||||
id: company.id,
|
||||
name: "${company.name} (${companyType})",
|
||||
originalName: company.name,
|
||||
isMainCompany: true,
|
||||
companyId: company.id,
|
||||
branchId: null,
|
||||
);
|
||||
companiesWithBranches.add(companyInfo);
|
||||
companies.add(companyInfo.name);
|
||||
|
||||
// 지점 정보 추가
|
||||
if (company.branches != null && company.branches!.isNotEmpty) {
|
||||
for (var branch in company.branches!) {
|
||||
final branchInfo = CompanyBranchInfo(
|
||||
id: branch.id,
|
||||
name: "${company.name} ${branch.name}",
|
||||
displayName: branch.name,
|
||||
originalName: branch.name,
|
||||
isMainCompany: false,
|
||||
companyId: company.id,
|
||||
branchId: branch.id,
|
||||
parentCompanyName: company.name,
|
||||
);
|
||||
companiesWithBranches.add(branchInfo);
|
||||
companies.add(branchInfo.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 나머지 데이터 로드
|
||||
final allUsers = dataService.getAllUsers();
|
||||
managers = allUsers.map((user) => user.name).toList();
|
||||
filteredManagers = managers;
|
||||
final allLicenses = dataService.getAllLicenses();
|
||||
licenses = allLicenses.map((license) => license.name).toList();
|
||||
if (companies.isEmpty) companies.add('기타');
|
||||
if (managers.isEmpty) managers.add('기타');
|
||||
if (licenses.isEmpty) licenses.add('기타');
|
||||
updateManagersState();
|
||||
|
||||
// 출고 회사 드롭다운 초기화
|
||||
availableCompaniesPerDropdown = [List.from(companies)];
|
||||
filteredManagersPerCompany = [List.from(managers)];
|
||||
hasManagersPerCompany = [hasManagers];
|
||||
|
||||
// 디버그 정보 출력
|
||||
debugPrint('드롭다운 데이터 로드 완료');
|
||||
debugPrint('장비 목록: ${_selectedEquipments?.length ?? 0}개');
|
||||
debugPrint('회사 및 지점 목록: ${companiesWithBranches.length}개');
|
||||
|
||||
// 수정 모드인 경우 기존 선택값 동기화
|
||||
if (isEditMode && equipmentOutId != null) {
|
||||
final equipmentOut = dataService.getEquipmentOutById(equipmentOutId!);
|
||||
if (equipmentOut != null && equipmentOut.company != null) {
|
||||
String companyName = '';
|
||||
|
||||
// 회사 이름 찾기
|
||||
for (String company in companies) {
|
||||
if (company.startsWith(equipmentOut.company!)) {
|
||||
companyName = company;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (companyName.isNotEmpty) {
|
||||
selectedCompanies[0] = companyName;
|
||||
filterManagersByCompanyAtIndex(companyName, 0);
|
||||
|
||||
// 기존 담당자 설정
|
||||
if (equipmentOut.manager != null) {
|
||||
selectedManagersPerCompany[0] = equipmentOut.manager;
|
||||
}
|
||||
}
|
||||
|
||||
// 라이센스 설정
|
||||
if (equipmentOut.license != null) {
|
||||
selectedLicense = equipmentOut.license;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 회사에 따라 담당자 목록 필터링
|
||||
void filterManagersByCompany(String? companyName) {
|
||||
if (companyName == null || companyName.isEmpty) {
|
||||
filteredManagers = managers;
|
||||
} else {
|
||||
// 회사 또는 지점 이름에서 CompanyBranchInfo 찾기
|
||||
CompanyBranchInfo? companyInfo = _findCompanyInfoByDisplayName(
|
||||
companyName,
|
||||
);
|
||||
|
||||
if (companyInfo != null && companyInfo.companyId != null) {
|
||||
int companyId = companyInfo.companyId!;
|
||||
final companyUsers =
|
||||
dataService
|
||||
.getAllUsers()
|
||||
.where((user) => user.companyId == companyId)
|
||||
.toList();
|
||||
|
||||
if (companyUsers.isNotEmpty) {
|
||||
filteredManagers = companyUsers.map((user) => user.name).toList();
|
||||
} else {
|
||||
filteredManagers = ['없음'];
|
||||
}
|
||||
} else {
|
||||
filteredManagers = ['없음'];
|
||||
}
|
||||
}
|
||||
|
||||
if (selectedManager != null &&
|
||||
!filteredManagers.contains(selectedManager)) {
|
||||
selectedManager =
|
||||
filteredManagers.isNotEmpty ? filteredManagers[0] : null;
|
||||
}
|
||||
updateManagersState();
|
||||
|
||||
// 첫 번째 회사에 대한 담당자 목록과 동기화
|
||||
if (filteredManagersPerCompany.isNotEmpty) {
|
||||
filteredManagersPerCompany[0] = List.from(filteredManagers);
|
||||
hasManagersPerCompany[0] = hasManagers;
|
||||
if (selectedManagersPerCompany.isNotEmpty) {
|
||||
selectedManagersPerCompany[0] = selectedManager;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 특정 인덱스의 회사에 따라 담당자 목록 필터링
|
||||
void filterManagersByCompanyAtIndex(String? companyName, int index) {
|
||||
if (companyName == null || companyName.isEmpty) {
|
||||
filteredManagersPerCompany[index] = managers;
|
||||
} else {
|
||||
// 회사 또는 지점 이름에서 CompanyBranchInfo 찾기
|
||||
CompanyBranchInfo? companyInfo = _findCompanyInfoByDisplayName(
|
||||
companyName,
|
||||
);
|
||||
|
||||
if (companyInfo != null && companyInfo.companyId != null) {
|
||||
int companyId = companyInfo.companyId!;
|
||||
final companyUsers =
|
||||
dataService
|
||||
.getAllUsers()
|
||||
.where((user) => user.companyId == companyId)
|
||||
.toList();
|
||||
|
||||
if (companyUsers.isNotEmpty) {
|
||||
filteredManagersPerCompany[index] =
|
||||
companyUsers.map((user) => user.name).toList();
|
||||
} else {
|
||||
filteredManagersPerCompany[index] = ['없음'];
|
||||
}
|
||||
} else {
|
||||
filteredManagersPerCompany[index] = ['없음'];
|
||||
}
|
||||
}
|
||||
|
||||
if (selectedManagersPerCompany[index] != null &&
|
||||
!filteredManagersPerCompany[index].contains(
|
||||
selectedManagersPerCompany[index],
|
||||
)) {
|
||||
selectedManagersPerCompany[index] =
|
||||
filteredManagersPerCompany[index].isNotEmpty
|
||||
? filteredManagersPerCompany[index][0]
|
||||
: null;
|
||||
}
|
||||
updateManagersStateAtIndex(index);
|
||||
|
||||
// 첫 번째 회사인 경우 기존 필드와 동기화
|
||||
if (index == 0) {
|
||||
filteredManagers = List.from(filteredManagersPerCompany[0]);
|
||||
hasManagers = hasManagersPerCompany[0];
|
||||
_selectedManager = selectedManagersPerCompany[0];
|
||||
}
|
||||
}
|
||||
|
||||
// 담당자 있는지 상태 업데이트
|
||||
void updateManagersState() {
|
||||
hasManagers =
|
||||
filteredManagers.isNotEmpty &&
|
||||
!(filteredManagers.length == 1 && filteredManagers[0] == '없음');
|
||||
}
|
||||
|
||||
// 특정 인덱스의 담당자 상태 업데이트
|
||||
void updateManagersStateAtIndex(int index) {
|
||||
hasManagersPerCompany[index] =
|
||||
filteredManagersPerCompany[index].isNotEmpty &&
|
||||
!(filteredManagersPerCompany[index].length == 1 &&
|
||||
filteredManagersPerCompany[index][0] == '없음');
|
||||
}
|
||||
|
||||
// 출고 회사 추가
|
||||
void addCompany() {
|
||||
// 이미 선택된 회사 제외한 리스트 생성
|
||||
List<String> availableCompanies = List.from(companies);
|
||||
for (String? company in selectedCompanies) {
|
||||
if (company != null) {
|
||||
availableCompanies.remove(company);
|
||||
}
|
||||
}
|
||||
|
||||
// 새 드롭다운 추가
|
||||
selectedCompanies.add(null);
|
||||
availableCompaniesPerDropdown.add(availableCompanies);
|
||||
selectedManagersPerCompany.add(null);
|
||||
filteredManagersPerCompany.add(List.from(managers));
|
||||
hasManagersPerCompany.add(false);
|
||||
}
|
||||
|
||||
// 가능한 회사 목록 업데이트
|
||||
void updateAvailableCompanies() {
|
||||
// 각 드롭다운에 대해 사용 가능한 회사 목록 업데이트
|
||||
for (int i = 0; i < selectedCompanies.length; i++) {
|
||||
List<String> availableCompanies = List.from(companies);
|
||||
|
||||
// 이미 선택된 회사 제외
|
||||
for (int j = 0; j < selectedCompanies.length; j++) {
|
||||
if (i != j && selectedCompanies[j] != null) {
|
||||
availableCompanies.remove(selectedCompanies[j]);
|
||||
}
|
||||
}
|
||||
|
||||
availableCompaniesPerDropdown[i] = availableCompanies;
|
||||
}
|
||||
}
|
||||
|
||||
// 선택 장비로 초기화
|
||||
void initializeWithSelectedEquipment(Equipment equipment) {
|
||||
manufacturer = equipment.manufacturer;
|
||||
name = equipment.name;
|
||||
category = equipment.category;
|
||||
subCategory = equipment.subCategory;
|
||||
subSubCategory = equipment.subSubCategory;
|
||||
serialNumber = equipment.serialNumber ?? '';
|
||||
barcode = equipment.barcode ?? '';
|
||||
quantity = equipment.quantity;
|
||||
hasSerialNumber = serialNumber.isNotEmpty;
|
||||
inDate = equipment.inDate;
|
||||
remarkController.text = equipment.remark ?? '';
|
||||
}
|
||||
|
||||
// 회사/지점 표시 이름을 통해 CompanyBranchInfo 객체 찾기
|
||||
CompanyBranchInfo? _findCompanyInfoByDisplayName(String displayName) {
|
||||
for (var info in companiesWithBranches) {
|
||||
if (info.name == displayName) {
|
||||
return info;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// 출고 정보 저장 (UI에서 호출)
|
||||
void saveEquipmentOut(Function(String) onSuccess, Function(String) onError) {
|
||||
if (formKey.currentState?.validate() != true) {
|
||||
onError('폼 유효성 검사 실패');
|
||||
return;
|
||||
}
|
||||
formKey.currentState?.save();
|
||||
|
||||
// 선택된 회사가 없는지 확인
|
||||
bool hasAnySelectedCompany = selectedCompanies.any(
|
||||
(company) => company != null,
|
||||
);
|
||||
if (!hasAnySelectedCompany) {
|
||||
onError('최소 하나의 출고 회사를 선택해주세요');
|
||||
return;
|
||||
}
|
||||
|
||||
// 기존 방식으로 첫 번째 회사 정보 처리
|
||||
String? companyName;
|
||||
if (selectedCompanies.isNotEmpty && selectedCompanies[0] != null) {
|
||||
CompanyBranchInfo? companyInfo = _findCompanyInfoByDisplayName(
|
||||
selectedCompanies[0]!,
|
||||
);
|
||||
if (companyInfo != null) {
|
||||
companyName =
|
||||
companyInfo.isMainCompany
|
||||
? companyInfo
|
||||
.originalName // 본사인 경우 회사 원래 이름
|
||||
: "${companyInfo.originalName} (${companyInfo.branchId})"; // 지점인 경우 지점 정보 포함
|
||||
} else {
|
||||
companyName = selectedCompanies[0]!.replaceAll(
|
||||
RegExp(r' \(.*\)\$'),
|
||||
'',
|
||||
);
|
||||
}
|
||||
} else {
|
||||
onError('최소 하나의 출고 회사를 선택해주세요');
|
||||
return;
|
||||
}
|
||||
|
||||
if (isEditMode && equipmentOutId != null) {
|
||||
final equipmentOut = dataService.getEquipmentOutById(equipmentOutId!);
|
||||
if (equipmentOut != null) {
|
||||
final updatedEquipmentOut = EquipmentOut(
|
||||
id: equipmentOut.id,
|
||||
equipment: equipmentOut.equipment,
|
||||
outDate: equipmentOut.outDate,
|
||||
status: returnType == '재입고' ? 'I' : 'R',
|
||||
company: companyName,
|
||||
manager: equipmentOut.manager,
|
||||
license: equipmentOut.license,
|
||||
returnDate: returnDate,
|
||||
returnType: returnType,
|
||||
remark: remarkController.text.trim(),
|
||||
);
|
||||
dataService.updateEquipmentOut(updatedEquipmentOut);
|
||||
onSuccess('장비 출고 상태 변경 완료');
|
||||
} else {
|
||||
onError('출고 정보를 찾을 수 없습니다');
|
||||
}
|
||||
} else {
|
||||
if (selectedEquipments != null && selectedEquipments!.isNotEmpty) {
|
||||
// 여러 회사에 각각 출고 처리
|
||||
List<String> successCompanies = [];
|
||||
|
||||
// 선택된 모든 회사에 대해 출고 처리
|
||||
for (int i = 0; i < selectedCompanies.length; i++) {
|
||||
if (selectedCompanies[i] == null) continue;
|
||||
|
||||
CompanyBranchInfo? companyInfo = _findCompanyInfoByDisplayName(
|
||||
selectedCompanies[i]!,
|
||||
);
|
||||
String curCompanyName;
|
||||
|
||||
if (companyInfo != null) {
|
||||
curCompanyName =
|
||||
companyInfo.isMainCompany
|
||||
? companyInfo
|
||||
.originalName // 본사인 경우 회사 원래 이름
|
||||
: "${companyInfo.originalName} (${companyInfo.branchId})"; // 지점인 경우 지점 정보 포함
|
||||
} else {
|
||||
curCompanyName = selectedCompanies[i]!.replaceAll(
|
||||
RegExp(r' \(.*\)\$'),
|
||||
'',
|
||||
);
|
||||
}
|
||||
|
||||
String? curManager = selectedManagersPerCompany[i];
|
||||
|
||||
if (curManager == null || curManager == '없음') {
|
||||
// 담당자 없는 회사는 건너뛰기
|
||||
continue;
|
||||
}
|
||||
|
||||
// 해당 회사에 모든 장비 출고 처리
|
||||
for (final equipmentData in selectedEquipments!) {
|
||||
final equipment = equipmentData['equipment'] as Equipment;
|
||||
final equipmentInId = equipmentData['equipmentInId'] as int;
|
||||
final newEquipmentOut = EquipmentOut(
|
||||
equipment: equipment,
|
||||
outDate: outDate,
|
||||
company: curCompanyName,
|
||||
manager: curManager,
|
||||
license: selectedLicense,
|
||||
remark: remarkController.text.trim(),
|
||||
);
|
||||
dataService.changeEquipmentStatus(equipmentInId, newEquipmentOut);
|
||||
}
|
||||
|
||||
successCompanies.add(companyInfo?.name ?? curCompanyName);
|
||||
}
|
||||
|
||||
if (successCompanies.isEmpty) {
|
||||
onError('모든 회사에 담당자가 없어 출고 처리할 수 없습니다');
|
||||
} else {
|
||||
onSuccess('${successCompanies.join(", ")} 회사로 다중 장비 출고 처리 완료');
|
||||
}
|
||||
} else if (selectedEquipmentInId != null) {
|
||||
final equipment = Equipment(
|
||||
manufacturer: manufacturer,
|
||||
name: name,
|
||||
category: category,
|
||||
subCategory: subCategory,
|
||||
subSubCategory: subSubCategory,
|
||||
serialNumber: (hasSerialNumber) ? serialNumber : null,
|
||||
barcode: barcode.isNotEmpty ? barcode : null,
|
||||
quantity: quantity,
|
||||
inDate: inDate,
|
||||
remark: remarkController.text.trim(),
|
||||
);
|
||||
|
||||
// 선택된 모든 회사에 대해 출고 처리
|
||||
List<String> successCompanies = [];
|
||||
|
||||
for (int i = 0; i < selectedCompanies.length; i++) {
|
||||
if (selectedCompanies[i] == null) continue;
|
||||
|
||||
CompanyBranchInfo? companyInfo = _findCompanyInfoByDisplayName(
|
||||
selectedCompanies[i]!,
|
||||
);
|
||||
String curCompanyName;
|
||||
|
||||
if (companyInfo != null) {
|
||||
curCompanyName =
|
||||
companyInfo.isMainCompany
|
||||
? companyInfo
|
||||
.originalName // 본사인 경우 회사 원래 이름
|
||||
: "${companyInfo.originalName} (${companyInfo.branchId})"; // 지점인 경우 지점 정보 포함
|
||||
} else {
|
||||
curCompanyName = selectedCompanies[i]!.replaceAll(
|
||||
RegExp(r' \(.*\)\$'),
|
||||
'',
|
||||
);
|
||||
}
|
||||
|
||||
String? curManager = selectedManagersPerCompany[i];
|
||||
|
||||
if (curManager == null || curManager == '없음') {
|
||||
// 담당자 없는 회사는 건너뛰기
|
||||
continue;
|
||||
}
|
||||
|
||||
final newEquipmentOut = EquipmentOut(
|
||||
equipment: equipment,
|
||||
outDate: outDate,
|
||||
company: curCompanyName,
|
||||
manager: curManager,
|
||||
license: selectedLicense,
|
||||
remark: remarkController.text.trim(),
|
||||
);
|
||||
dataService.changeEquipmentStatus(
|
||||
selectedEquipmentInId!,
|
||||
newEquipmentOut,
|
||||
);
|
||||
|
||||
successCompanies.add(companyInfo?.name ?? curCompanyName);
|
||||
break; // 한 장비는 한 회사에만 출고
|
||||
}
|
||||
|
||||
if (successCompanies.isEmpty) {
|
||||
onError('모든 회사에 담당자가 없어 출고 처리할 수 없습니다');
|
||||
} else {
|
||||
onSuccess('${successCompanies.join(", ")} 회사로 장비 출고 처리 완료');
|
||||
}
|
||||
} else {
|
||||
final equipment = Equipment(
|
||||
manufacturer: manufacturer,
|
||||
name: name,
|
||||
category: category,
|
||||
subCategory: subCategory,
|
||||
subSubCategory: subSubCategory,
|
||||
serialNumber: null,
|
||||
barcode: null,
|
||||
quantity: 1,
|
||||
inDate: inDate,
|
||||
remark: remarkController.text.trim(),
|
||||
);
|
||||
|
||||
// 선택된 모든 회사에 대해 출고 처리
|
||||
List<String> successCompanies = [];
|
||||
|
||||
for (int i = 0; i < selectedCompanies.length; i++) {
|
||||
if (selectedCompanies[i] == null) continue;
|
||||
|
||||
CompanyBranchInfo? companyInfo = _findCompanyInfoByDisplayName(
|
||||
selectedCompanies[i]!,
|
||||
);
|
||||
String curCompanyName;
|
||||
|
||||
if (companyInfo != null) {
|
||||
curCompanyName =
|
||||
companyInfo.isMainCompany
|
||||
? companyInfo
|
||||
.originalName // 본사인 경우 회사 원래 이름
|
||||
: "${companyInfo.originalName} (${companyInfo.branchId})"; // 지점인 경우 지점 정보 포함
|
||||
} else {
|
||||
curCompanyName = selectedCompanies[i]!.replaceAll(
|
||||
RegExp(r' \(.*\)\$'),
|
||||
'',
|
||||
);
|
||||
}
|
||||
|
||||
String? curManager = selectedManagersPerCompany[i];
|
||||
|
||||
if (curManager == null || curManager == '없음') {
|
||||
// 담당자 없는 회사는 건너뛰기
|
||||
continue;
|
||||
}
|
||||
|
||||
final newEquipmentOut = EquipmentOut(
|
||||
equipment: equipment,
|
||||
outDate: outDate,
|
||||
company: curCompanyName,
|
||||
manager: curManager,
|
||||
license: selectedLicense,
|
||||
remark: remarkController.text.trim(),
|
||||
);
|
||||
dataService.addEquipmentOut(newEquipmentOut);
|
||||
|
||||
successCompanies.add(companyInfo?.name ?? curCompanyName);
|
||||
}
|
||||
|
||||
if (successCompanies.isEmpty) {
|
||||
onError('모든 회사에 담당자가 없어 출고 처리할 수 없습니다');
|
||||
} else {
|
||||
onSuccess('${successCompanies.join(", ")} 회사로 새 출고 장비 추가 완료');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 날짜 포맷 유틸리티
|
||||
String formatDate(DateTime date) {
|
||||
return '${date.year}-${date.month.toString().padLeft(2, '0')}-${date.day.toString().padLeft(2, '0')}';
|
||||
}
|
||||
|
||||
void dispose() {
|
||||
remarkController.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/// 회사 및 지점 정보를 저장하는 클래스
|
||||
class CompanyBranchInfo {
|
||||
final int? id;
|
||||
final String name; // 표시용 이름 (회사명 + 지점명 또는 회사명 (유형))
|
||||
final String originalName; // 원래 이름 (회사 본사명 또는 지점명)
|
||||
final String? displayName; // UI에 표시할 이름 (주로 지점명)
|
||||
final bool isMainCompany; // 본사인지 지점인지 구분
|
||||
final int? companyId; // 회사 ID
|
||||
final int? branchId; // 지점 ID
|
||||
final String? parentCompanyName; // 부모 회사명 (지점인 경우)
|
||||
|
||||
CompanyBranchInfo({
|
||||
required this.id,
|
||||
required this.name,
|
||||
required this.originalName,
|
||||
this.displayName,
|
||||
required this.isMainCompany,
|
||||
required this.companyId,
|
||||
required this.branchId,
|
||||
this.parentCompanyName,
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user